operator= 必须返回 *this 引用以支持链式赋值、避免深拷贝开销、防止浅拷贝陷阱、确保自赋值安全、满足stl要求,并使链式调用合法。

operator= 必须返回 self& 才能支持 a = b = c
链式赋值不是语法糖,而是 C++ 内置语义的直接体现。表达式 a = b = c 按右结合解析为 a = (b = c),因此 b = c 必须产生一个可被再次赋值的左值——即 b 自身的引用。如果 operator= 返回 void,a = (b = c) 编译失败;如果返回 self(值),则 b = c 构造临时对象,后续赋值作用于该临时对象,a 实际得不到 c 的值。
返回引用避免深拷贝开销和浅拷贝陷阱
返回 *this 是零成本操作;返回值类型会触发拷贝构造,而默认拷贝构造对含指针成员的类是浅拷贝,极易引发双重释放。即使你写了深拷贝构造函数,也多一次无谓的内存分配与拷贝。更关键的是:一旦返回值,就绕过了自赋值检查逻辑(如 if (this != &rhs)),可能让资源管理出错。
- 含
char*或std::unique_ptr成员的类,返回值会强制调用拷贝构造——而你很可能没写它,或写得不正确 - 返回引用后,
(a = b).modify()这类链式调用才合法;返回值则无法对赋值结果调用成员函数 - STL 容器(如
std::vector<t></t>)内部大量依赖T& operator=(const T&),不满足此签名会导致编译失败或未定义行为
不返回引用的后果往往延迟暴露
很多场景下,不返回引用也能“跑通”:比如只写 a = b; 单条语句、或只用在 std::map 插入时的 it->second = x;。但问题会在这些地方突然爆发:
-
std::sort或std::stable_sort在内部交换元素时,会反复调用operator=,若返回值,性能暴跌且可能因临时对象析构顺序异常崩溃 - 使用
auto&&接收赋值结果(如auto&& ref = a = b;),返回值会让ref绑定到临时对象,生命周期仅限当前表达式 - 某些编译器对返回值优化(RVO/NRVO)不生效于
operator=,尤其涉及模板或条件分支时
标准写法必须带自赋值检查 + return *this
最简安全实现不是只写 return *this; 就完事。典型结构是:
MyClass& operator=(const MyClass& rhs) {
if (this == &rhs) return *this; // 自赋值检查不可省
// 释放当前资源(如有)
// 深拷贝 rhs 资源
return *this; // 唯一合法返回方式
}
注意:用拷贝-交换惯用法(copy-and-swap)可省去显式自赋值检查,但前提是 swap 无异常且 MyClass(const MyClass&) 正确实现——这反而提高了门槛。对多数场景,显式检查 + return *this 最直白可靠。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











