==和!=默认按位比较内置类型,自定义类必须重载;std::string/vector的==是严格逐元素相等;浮点数需用误差判断;c++20支持=default;容器查找依赖==语义正确性。

相等运算符 == 和不等运算符 != 的基本行为
它们在 C++ 中默认按位比较内置类型(如 int、double、指针),只要值完全一致就返回 true。但对自定义类,默认不提供重载,直接使用会编译报错:invalid operands to binary expression ('MyClass' and 'MyClass')。
常见误用是以为 std::string 或 std::vector 的 == 是“内容模糊匹配”——其实它是逐元素严格相等判断,大小写敏感、顺序敏感、空格敏感。
-
std::string("abc") == std::string("ABC")→false -
std::vector<int>{1,2} == std::vector<int>{1,2,0}</int></int>→false(长度不同) - 浮点数慎用:
0.1 + 0.2 == 0.3几乎总是false,应改用误差范围判断
自定义类必须手动重载 operator== 和 operator!=
不重载就无法用 == 比较两个对象;只重载 == 而不重载 !=,会导致 a != b 编译失败(C++20 前不支持自动生成)。
推荐写法:在类内声明为 friend 或 const 成员函数,参数为 const& 避免拷贝:
struct Point {
int x, y;
friend bool operator==(const Point& a, const Point& b) {
return a.x == b.x && a.y == b.y;
}
friend bool operator!=(const Point& a, const Point& b) {
return !(a == b);
}
};
- 不要在重载中调用
memcmp或裸指针比较,成员可能有 padding 或非平凡类型 - 若类含
std::unique_ptr等资源句柄,需明确语义:比的是所指对象?还是指针地址? - C++20 起可加
= default让编译器生成逐成员比较(要求所有成员可比较),但需注意隐式转换和私有成员访问权限
容器和算法里用 == 的隐含要求
像 std::find、std::map::find、std::unordered_map 的查找,底层都依赖 ==。如果自定义类型没重载它,或重载逻辑与业务不符(比如把两个不同 ID 的用户视为相等),结果会出人意料。
-
std::find(v.begin(), v.end(), target):要求v元素类型与target类型可被==比较 -
std::unordered_map<key val></key>:仅靠==不够,还必须提供哈希函数(std::hash<key></key>) - 用
==判断std::optional<t></t>相等时,若两者皆为空则相等;一空一非空则不等;都非空则递归比较内部值
容易被忽略的陷阱:字面量、隐式转换和 ADL
写 obj == nullptr 时,若类重载了接受 std::nullptr_t 的 operator==,可能意外触发;更常见的是字符串字面量引发的临时对象生命周期问题:
-
std::string s = "hello"; if (s == "world")→ 正确,C++ 标准允许string与 C 字符串字面量比较 - 但自定义类若只重载了
operator==(const MyClass&, const MyClass&),就不能写obj == 42,除非提供了接受int的重载或定义了MyClass(int)构造函数且未加explicit - ADL(参数依赖查找)可能导致意外找到非预期的
operator==:若某个命名空间中定义了针对你类型的自由函数operator==,即使没using,它也可能被选中
真正麻烦的不是语法怎么写,而是想清楚“什么情况下两个对象该算相等”——这个语义一旦定错,后续所有查找、去重、缓存逻辑都会连锁失效。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











