返回值必须是值类型或const引用,否则会绑定到销毁的临时对象导致悬垂引用;operator=应复用operator而非相反;operator/需主动检查除零并抛异常。

重载 operator+ 和 operator- 时,为什么返回值必须是值类型或 const 引用?
因为非 const 左值引用会绑定到临时对象,而临时对象在表达式结束后就销毁。比如 a + b 返回局部对象,若声明为 MyClass& operator+(...),调用方拿到的是悬垂引用。
- 正确做法:返回
MyClass(值语义,安全但可能有拷贝开销)或const MyClass&(仅当返回的是已有对象,如成员或参数) - 常见错误:写成
MyClass& operator+(const MyClass& a, const MyClass& b),编译可能通过,运行时行为未定义 - 如果类内部管理动态资源(如指针),确保拷贝构造函数和析构函数已正确定义,否则值返回会引发浅拷贝问题
operator*= 和 operator= 的实现顺序不能颠倒
复合赋值运算符(如 +=、*=)应优先复用普通运算符 + 赋值逻辑,而不是反过来。否则容易破坏自赋值安全性和异常安全性。
- 推荐模式:
MyClass& operator*=(const MyClass& rhs) { *this = *this * rhs; return *this; } - 错误模式:在
operator*中调用operator*=—— 这会导致循环依赖,且operator*本应是纯函数(不修改左操作数) - 注意:若
operator*返回的是临时对象,*this = ...会触发移动赋值(C++11+),前提是定义了移动赋值运算符;否则走拷贝赋值,性能可能下降
重载 operator/ 前必须检查除零,且不能只靠断言
用户传入的参数不可信,assert 在 NDEBUG 下失效,生产环境会直接崩溃或产生未定义行为。
- 对整数类型:显式判断分母是否为 0,抛出
std::invalid_argument或自定义异常 - 对浮点类型:用
std::isnan()和std::isinf()检查非法输入,再判断是否接近零(如std::abs(rhs) ) - 不要依赖
/自带的硬件除零陷阱 —— C++ 标准不保证它抛异常,多数平台只是产生SIGFPE,难以捕获和处理
全局重载 vs 成员函数重载:什么时候必须用友元?
当左操作数不是当前类类型(比如 int * MyClass),且你希望支持隐式转换时,只能用非成员函数;而访问私有成员又需要它成为友元。
立即学习“C++免费学习笔记(深入)”;
- 例如:想支持
2 * obj,operator*必须是全局函数,且声明为friend才能读取obj的私有数据 - 成员版本天然支持
obj * 2(左操作数是类类型),但不支持2 * obj - 友元函数不是类成员,不受访问控制限制,但也意味着它绕过了封装契约 —— 修改私有布局时,所有友元函数都得同步更新
事情说清了就结束。最常被忽略的是:复合赋值运算符的异常安全性,以及友元函数与类内实现的耦合程度。这两处一旦出错,调试成本远高于初写时多花的两分钟。











