std::midpoint 是 C++20 引入的安全中点计算函数,通过类型特化避免溢出:整型用无溢出位运算,浮点处理特殊值,指针要求同数组;支持整型、浮点、同数组指针,不支持自定义类型或混合符号类型。

std::midpoint 是 C++20 引入的真正安全的中点计算工具,它不依赖加法,因此能避免 a + b 溢出——这是 (a + b) / 2 或 a + (b - a) / 2 都无法完全规避的问题。
为什么 std::midpoint 比手写逻辑更可靠
很多人以为 a + (b - a) / 2 就够安全,但它在有符号整数下仍有隐患:当 a 为负、b 为正且差值极大时,b - a 可能溢出(例如 INT_MIN 和 INT_MAX)。std::midpoint 内部按类型分路径处理:
- 对整型:用位运算或无溢出算术(如先右移再补偿),不出现任何中间加减溢出
- 对浮点:直接计算,但会处理
±inf和NaN的边界情况 - 对指针:仅允许相同数组内的指针,编译期检查
std::is_same_v和可比较性
哪些类型能用 std::midpoint
必须满足可比较、可相减(对指针还要求同数组),常见可用类型包括:
- 所有有符号/无符号整型(
int,uint64_t,char等) - 浮点类型(
float,double),但注意std::midpoint(1.0f, 3.0f)返回float,不提升 - 指向同一数组的指针(
int*,const char*),std::midpoint(p, q)等价于p + (q - p) / 2,但带安全校验 - 不能用于用户自定义类型,除非显式特化
std::midpoint并满足约束
常见误用和编译错误
直接调用失败往往不是语法问题,而是类型或语义违规:
立即学习“C++免费学习笔记(深入)”;
-
std::midpoint(INT_MAX, 1)编译通过,结果是INT_MAX(向下取整),符合标准定义,不是 bug -
std::midpoint(ptr1, ptr2)若ptr1和ptr2不指向同一数组,行为未定义(不报错,但运行时可能崩溃) -
std::midpoint(1u, -1)编译失败:混合有符号/无符号,类型不匹配,必须显式转换 - 在 C++17 或更低版本中使用会触发
error: 'midpoint' is not a member of 'std',需确认编译器支持(GCC 10+、Clang 11+、MSVC 19.28+)并启用-std=c++20
替代方案对比:什么时候不该用 std::midpoint
它专为「两点之间中点」设计,不是通用平均函数:
- 需要三个及以上数的平均值?别用它,改用
std::accumulate+ 类型提升 - 要向上取整中点(如二分查找上界)?
std::midpoint总是向下取整,应手动写a + (b - a + 1) / 2并确保不溢出 - 处理时间戳或自定义单位(如毫秒差值)?先转成
int64_t差值再算,std::midpoint不接受自定义单位类 - 性能敏感场景?它比
(a + b) >> 1稍慢(尤其整型分支判断),但换来的安全性通常值得
最易被忽略的一点:它的返回类型严格是参数类型的公共类型,不会自动提升——std::midpoint(int8_t{100}, int8_t{100}) 返回 int8_t,溢出风险仍在,只是发生在结果赋值时,而非中间计算。用之前务必确认目标范围。










