<p>std::midpoint比(a + b) / 2更安全,因为后者在指针上非法(不支持加法与除法),而std::midpoint采用a + (b - a) / 2避免溢出和越界,但要求两指针同类型、指向同一数组且有效。</p>

std::midpoint在指针运算中为什么比(a + b) / 2更安全
直接用 (a + b) / 2 算两个指针中点,在大多数情况下会编译失败或触发未定义行为——因为指针不支持除法,且 a + b 本身非法(C++ 不允许两个指针相加)。std::midpoint 是 C++20 引入的专用工具,专为避免整数溢出和指针算术越界设计,它内部采用 a + (b - a) / 2 的等价逻辑,确保中间结果始终在合法范围内。
使用std::midpoint计算指针中点的正确写法
必须满足:两个指针指向同一数组(或 one-past-the-end),且类型相同、可比较。否则行为未定义。
-
std::midpoint要求参数是同一类型的指针,比如int*和int*,不能混用int*与const int*(除非显式转换) - 传入空指针(
nullptr)是未定义行为,必须确保两者都有效或至少一个是合法的数组边界 - 示例:
int arr[10] = {};<br>auto mid = std::midpoint(arr, arr + 10); // ✅ 指向 arr[5]<br>auto bad = std::midpoint(&arr[0], &arr[5] + 10); // ❌ 越界,未定义
常见错误:误用在非数组指针或跨对象场景
把 std::midpoint 用在动态分配但非连续的对象上(如两个 new 出来的 int*),或不同数组的指针之间,会导致未定义行为——标准只要求它对“同一数组内”成立。
- 错误示例:
int* p1 = new int;<br>int* p2 = new int;<br>auto x = std::midpoint(p1, p2); // ❌ 未定义,p1 和 p2 不属同一对象
- 即使地址数值上接近,只要不是同一数组,
std::midpoint不保证结果有意义 - 对
std::vector::data()和std::vector::data() + size()是安全的;但对std::vector迭代器(如begin()/end())不能直接传入——需先转成原生指针:std::midpoint(v.data(), v.data() + v.size())
兼容性与替代方案(C++17及更早)
std::midpoint 是 C++20 特性,若项目仍用 C++17 或更低版本,需手动实现等效逻辑,但要注意整型提升和符号问题。
立即学习“C++免费学习笔记(深入)”;
- 安全的手动写法(适用于同类型指针
T*):T* safe_mid(T* a, T* b) {<br> return a + (b - a) / 2;<br>}注意:该表达式依赖b >= a,否则b - a为负,除法截断方向依赖实现(C++11 起向零截断,通常安全) - 若担心有符号整型溢出(极长数组),可用
std::ptrdiff_t中间转换:a + static_cast<:ptrdiff_t>(b - a) / 2</:ptrdiff_t> - 切勿用
(uintptr_t(a) + uintptr_t(b)) / 2—— 地址可能不对齐,且失去类型安全性
实际用时最容易忽略的是“同一数组”这个隐含前提——它不检查,也不报错,只默默给出无意义结果。写二分查找或内存分块时,务必确认两个指针真正在同一个连续内存块里。


















