重载 operator== 是最直接的方式;必须按内容而非内存布局比较,签名应为 bool operator==(const t& other) const,注意指针、容器、异常安全及 c++20 default 限制。

重载 operator== 是最直接的方式
默认情况下,C++ 对类对象使用的是逐字节比较(即内存布局相同才相等),这几乎总是错的。要按“内容相同”判断,必须自己定义逻辑——也就是重载 operator==。
常见错误是只比较部分成员,比如忽略指针所指内容、忽略容器大小或顺序、漏掉 const 限定符导致无法用于 const 对象。
- 函数签名必须是
bool operator==(const T& other) const,否则可能无法参与某些标准算法(如std::find) - 如果类有指针成员,别直接比地址;要比较其指向的内容是否等价(比如用
*ptr == *other.ptr) - 若含
std::vector或std::string,它们已重载==,可直接写v1 == v2 - 避免在
==中调用可能抛异常的函数,否则破坏比较操作的“无副作用”直觉
用 std::equal_to 或 std::ranges::equal 前先确认底层支持
std::equal_to<t>{}(a, b)</t> 本质还是调 a == b,它不提供额外逻辑。真正有用的是 std::ranges::equal——但仅适用于可迭代对象(如数组、vector),不能直接用于任意两个 class 对象。
容易踩的坑:有人误以为传入两个对象就能自动展开比较所有字段,其实不会。它只对范围有效,比如:
std::vector<int> v1 = {1,2,3}, v2 = {1,2,3};
bool same = std::ranges::equal(v1, v2); // ✅ 正确</int>
对自定义结构体,除非你把它设计成能隐式转成视图(如通过 begin()/end()),否则这条路走不通。
自动生成(C++20 = default)只适合“纯数据类”
C++20 允许对聚合类(aggregate)用 operator== = default;,编译器会逐个成员调用 ==。但它有严格前提:
- 类必须是聚合类型:无用户声明构造函数、无私有/受保护非静态成员、无虚函数、无基类等
- 所有成员类型都必须支持
==(内置类型、标准容器、其他也 defaulted 的类) - 一旦加了私有成员或自定义构造函数,
= default就失效,必须手写
例如这个不行:
struct Person {
std::string name;
private:
int id; // 私有成员 → 不再是聚合类 → 不能 = default
};
别依赖 memcmp 或 memcpy 比较对象
有人试图用 memcmp(&a, &b, sizeof(T)) 判断相等,这是危险的:
- 类中有 padding 字节时,这些字节值未定义,memcmp 可能返回 false 即使逻辑内容相同
- 含浮点成员时,-0.0 和 +0.0 的 bit 表示不同,但语义相等
- 有指针或引用成员时,比的是地址值,不是所指内容
- 有虚函数表指针(vptr)时,即使两个对象内容一样,vptr 地址也可能不同
只有 POD 类型且明确无 padding、无浮点、无指针时,memcmp 才勉强可用——但这种场景极少,不值得冒险。
复杂点往往藏在“看起来一样”的成员上:比如一个 std::shared_ptr<t></t>,内容相同是指所指对象相等,还是指 ptr 本身相等?这个语义必须由你明确定义,编译器不会猜。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











