运算符重载是接口契约而非语法糖;必须用成员函数的包括operator=、[]、()、->及修改自身状态的+=、++等;需左操作数为其他类型或对等时用友元;参数多用const T&,返回值按语义选T或T&;非const成员函数不可用于const对象,故[]等需双版本。

运算符重载不是语法糖,是接口契约——写错一个 const 或漏掉 &,调用就可能静默失败或编译不过。
什么时候必须用成员函数重载
涉及修改对象自身状态、或需要访问 private 成员时,优先用成员函数。比如 operator+=、operator++(前置)、operator= —— 它们天然需要修改 this 指向的对象。
-
operator=必须是成员函数(编译器会隐式生成默认版本,自定义时必须显式声明为成员) - 赋值、下标
[]、函数调用()、成员访问->这四个运算符只能是成员函数 - 前置递增
++a通常返回T&,直接返回*this;若写成友元或非成员,无法自然返回引用到当前对象
什么时候该用友元函数重载
当运算符需要左侧操作数是其他类型(比如 int + MyString),或左右操作数地位完全对等(如 a + b),且需访问类的私有成员时,用 friend 函数更自然。
operator 和operator>>几乎总是友元:左侧是std::ostream&或std::istream&,不可能是你的类成员-
operator+、operator==等二元运算符,若希望支持123 + obj这种左值为内置类型的表达式,就不能写成成员函数(成员函数的左操作数固定是当前类) - 友元函数在类内声明(加
friend关键字),定义可放在类外,不占用类的public/private区域
参数和返回值怎么选才安全
核心原则:按需传递,按需返回 —— 不多也不少。常见错误是传值导致意外拷贝,或返回临时对象的引用。
立即学习“C++免费学习笔记(深入)”;
- 输入参数:一般用
const T&(避免拷贝,又防误改);只有极少数场景(如移动语义)用T&& - 返回值:
operator+返回T(值语义,合理);operator+=返回T&(支持链式调用:a += b += c) - 千万别返回局部变量的引用或指针,比如
return &temp;或return std::string("abc");后接.c_str() - 如果运算符逻辑不修改对象(如
operator+、operator==),函数本身要加const限定(成员函数时)
容易被忽略的隐式陷阱
很多问题不报错,但行为反直觉:比如 operator bool() 导致 if (obj) { ... } 可用,却也允许 obj + 1 这种荒谬表达式通过编译。
- 避免无约束的类型转换运算符:
operator int()或operator void*()会让隐式转换失控;C++11 起应加explicit -
operator[]通常要提供 const 和非 const 两个重载,否则const MyVec v; v[0] = 1;会编译失败,而v[0]读取也会因缺少 const 版本报错 - 重载
new/delete时,务必匹配:全局重载要声明在全局作用域;类内重载只影响该类,且需同时提供数组版本(operator new[])
真正难的不是写出来,而是想清楚「这个运算符在用户代码里会被怎么用」——比如 obj == nullptr 是否合法?obj + obj 和 obj + 5 是否都该支持?这些边界一旦定错,后续很难补救。









