operator+必须返回新对象而非引用,以避免悬垂引用;应使用const T&参数防止修改和拷贝;支持内置类型左操作数时需用全局函数;移动语义通常非必需。

operator+ 必须返回值,不能返回引用
重载 operator+ 的核心原则是:它应该像内置类型加法一样,产生一个**新对象**,而不是修改任一操作数。因此函数必须返回 T(或 const T),绝不能返回 T& 或 T&&——否则可能引发悬垂引用或意外修改。
常见错误是把 operator+ 写成类似 operator+= 的就地修改风格:
MyClass& operator+(const MyClass& a, const MyClass& b) { // ❌ 危险!
a.data += b.data; // 试图修改 const 引用
return a; // 返回局部/临时对象的引用?崩溃风险
}
正确写法是构造并返回新对象:
MyClass operator+(const MyClass& a, const MyClass& b) {
return MyClass(a.data + b.data); // ✅ 独立副本
}
成员函数 vs 全局函数:什么时候选哪个
选择实现方式的关键在于**左操作数是否必须是当前类类型**:
立即学习“C++免费学习笔记(深入)”;
- 如果只支持
a + b(a是本类对象),用成员函数更自然,this隐式绑定左操作数 - 如果还要支持
int + obj或double + obj这类左操作数非本类的情况,必须用全局(非成员)函数,否则编译器无法将内置类型隐式转换为左操作数
例如想让 5 + obj 合法,就得定义全局函数:
MyClass operator+(int n, const MyClass& obj) { // ✅ 左边是 int
return MyClass(n + obj.data);
}
而成员函数只能处理 obj + 5(右操作数可转换),无法覆盖 5 + obj。
const 正确性与参数传递方式
两个参数都应声明为 const T&,原因很实际:
- 避免无谓拷贝:传引用比传值快,尤其对象较大时
- 允许对常量对象、临时对象调用:比如
func() + obj中func()返回临时对象,只能绑定到const& - 防止误改输入:加法不该改变原对象
反例:
MyClass operator+(MyClass a, MyClass b) { // ❌ 值传递 → 多余拷贝
return a += b; // 还可能触发移动语义混乱
}
再强调一次:不要在 operator+ 里调用 operator+= 并返回引用——那是 operator+= 的职责,不是 + 的。
移动语义要不要加?看场景
C++11 后可以为 operator+ 提供右值重载,但**绝大多数情况不需要**。标准做法是只写一个 const T& 版本,让编译器自动对返回值启用移动构造(如果类有移动构造函数)。
只有当你明确知道左操作数是即将销毁的临时对象(比如链式表达式中间结果),且对象内部资源昂贵(如大 vector、文件句柄等),才考虑补充右值重载:
MyClass operator+(MyClass&& a, const MyClass& b) {
a.data += b.data;
return std::move(a); // ✅ 利用已有资源,避免深拷贝
}
但注意:这个版本和 const& 版本必须逻辑一致,且不能破坏交换律假设(a + b == b + a)。多数业务类没这个必要,先写好基础版本再说。
最容易被忽略的是:返回值类型别名、模板类中的友元声明位置、以及和 operator+= 的分工边界——一旦混用,调试时会发现对象状态莫名改变或内存被重复释放。








