std::midpoint能防溢出是因为它用位运算或无溢出算术实现,而非直接(a+b)/2;对整型、指针、浮点均安全,要求参数类型相同且满足特定约束。

std::midpoint 为什么能防溢出
直接用 (a + b) / 2 算中点,在整数类型上容易溢出——比如 int 的 a = INT_MAX、b = 1,加法就触发未定义行为。而 std::midpoint(C++20 引入)内部用位运算或无溢出算术实现,对整型、指针、浮点都安全,且语义明确:它返回「位于 a 和 b 正中间的值」,不是简单除法模拟。
整数中点计算必须用 std::midpoint 而非手动公式
常见错误是写成 a + (b - a) / 2 或 (a & b) + ((a ^ b) >> 1),前者对有符号负数可能截断(如 a = -1, b = 1),后者在某些编译器优化下仍可能 UB。正确做法只有调用标准库:
#include <numeric> int a = INT_MAX, b = INT_MIN; auto m = std::midpoint(a, b); // 安全,结果为 -1 </numeric>
-
std::midpoint对signed和unsigned整型都适用,自动处理符号扩展 - 参数类型必须相同,
std::midpoint(1, 1L)编译失败——需显式转换 - 不支持混合浮点/整型,
std::midpoint(1.0f, 2)也不行
指针中点计算是唯一安全的指针差值场景
对同一数组内指针求中点,std::midpoint(p, q) 是 C++20 中唯一被保证无 UB 的方式。手动写 p + (q - p) / 2 在 q - p 溢出时(比如大数组跨地址空间边界)仍是未定义行为。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
int arr[1000]; auto p = arr, q = arr + 999; auto mid = std::midpoint(p, q); // 安全,等价于 arr + 499
- 仅限同一数组(含 one-past-the-end)内的指针,否则行为未定义
- 不能用于
void*或函数指针——类型必须是可比较的T* - 底层依赖
std::distance,所以要求指针满足随机访问迭代器语义
浮点中点的精度与舍入差异
对 float 或 double,std::midpoint 不等于 (a + b) * 0.5。它使用更精确的算法(如 FMA 或分段计算),避免中间和溢出或精度损失。例如 a = 1e30, b = -1e30,(a + b) / 2 得 0(但 a + b 先溢出为 inf),而 std::midpoint 正确返回 0.0。
- 当
a和b同号时,结果严格介于两者之间;异号时可能恰好为零 - IEEE 754 舍入模式不影响结果——
std::midpoint自身控制舍入 - 性能略低于裸加法除法,但代价换来的是确定性与安全性
实际用的时候,别再手写中点逻辑了。只要编译器支持 C++20(GCC 10+、Clang 11+、MSVC 19.28+),就直接用 std::midpoint。最容易被忽略的是类型一致性——传两个 int 就别混进 long long,指针必须同数组,浮点别和整数混用。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










