指针比较运算符仅对同一数组或对象内的指针合法,跨数组或无关对象的、=比较行为未定义;==、!=虽语法合法,但仅当指向同一对象或数组元素时结果确定,否则未定义。

指针比较运算符只适用于同一数组或对象内
直接拿两个无关指针做 ==、!=、、<code>> 是合法语法,但行为未定义——除非它们指向同一数组(含数组末尾的哨兵位置)或同一对象的成员。编译器不会报错,运行时可能看似正常,也可能崩溃或返回错误结果。
常见错误现象:ptr1 在不同 <code>new 分配的内存块上比较,结果不可靠;结构体中非连续成员(如含虚函数或多重继承)的地址比较也容易出问题。
- 安全场景:遍历数组时用
ptr 判断边界 - 不安全场景:比较两个独立
new int返回的指针,或跨std::vector的data()指针 - 结构体成员指针比较需确保在同一对象内,且成员在内存中实际连续(可查
offsetof或用std::addressof验证)
== 和 != 是唯一能用于任意同类型指针的比较
== 和 != 只判断地址值是否相等,不要求指针有可比序关系。这是唯一能在任意两个同类型指针间安全使用的比较运算符(包括空指针、nullptr、无效指针,只要不解引用)。
使用场景:检查指针是否为空、是否指向同一对象、是否为迭代器 end() 位置。
-
if (p == nullptr)安全;if (p == 0)也合法但推荐用nullptr -
if (it == container.end())是标准做法,依赖容器迭代器重载的== - 注意:
void*不能直接参与==,需先转为具体类型指针再比较
使用 等关系运算符前必须确认可排序性
C++ 标准仅保证对同一数组/对象内的指针,、<code>、<code>>、>= 有明确定义(按地址升序)。超出此范围,即使两个指针都有效,结果也是未定义行为(UB),优化器可能据此生成错误代码。
性能影响:某些平台(如带地址空间布局随机化 ASLR 的系统)下,指针值本身无自然序,强行比较会掩盖真实数据依赖,干扰编译器优化。
- 正确写法:
int arr[10]; int* p = arr; while (p - 错误写法:
int* a = new int; int* b = new int; if (a —— 不可移植,不应依赖 - 替代方案:如需排序多个独立分配的指针,应存入容器(如
std::vector<int></int>)后用std::sort配合自定义比较器(例如按地址数值强制转换为uintptr_t),但要清楚这属于实现细节依赖
迭代器与智能指针的比较行为差异
原生指针和迭代器看似相似,但迭代器的比较运算符语义由容器定义——通常要求同源(同一容器、同迭代器类别),否则行为未定义。智能指针如 std::shared_ptr 和 std::unique_ptr 默认只支持 == 和 !=(比较所指对象地址),不提供 等操作,除非显式特化或用 <code>std::less 等函数对象。
-
std::vector::iterator支持,但 <code>std::list::iterator不支持(非随机访问) std::shared_ptr<int> a, b; if (a 编译失败;需写 <code>std::less<:shared_ptr>>{}(a, b)</:shared_ptr>才能用地址比较- 自定义类的迭代器若想支持
,必须继承自 <code>std::random_access_iterator_tag并正确定义operator-
最容易被忽略的是:把原生指针的“地址可比”直觉套用到所有指针类抽象上,结果在迭代器或智能指针上踩坑。真要比较地址大小,老老实实转 uintptr_t 最可控。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











