Effective C++ 条款10:令operator=返回一个reference to *this
Effective C++ 条款10:令operator=返回一个reference to *this
核心思想:赋值操作符(operator=
)应始终返回当前对象的引用(*this
),以实现连锁赋值并保持与内置类型一致的语义。
⚠️ 1. 问题场景:违反连锁赋值语义
class Widget {
public:void operator=(const Widget& rhs) { // 错误:返回voidvalue = rhs.value;}
private:int value;
};int main() {Widget a, b, c;a = b = c; // 错误:void类型不能作为右值return 0;
}
结果:
- 编译错误:
void
类型不能用于赋值操作 - 破坏与内置类型(如
int
)一致的赋值语义
✅ 2. 解决方案:返回 *this 引用
(1) 标准赋值操作符实现(⭐️必须)
class Widget {
public:Widget& operator=(const Widget& rhs) { // 返回当前对象引用if (this != &rhs) { // 自赋值检查(条款11)value = rhs.value;}return *this; // 关键:返回 *this}
private:int value;
};
(2) 复合赋值操作符实现(+=, -=等)
Widget& operator+=(const Widget& rhs) {value += rhs.value;return *this; // 同样返回 *this
}// 使用:
Widget x, y, z;
x = y += z; // 支持连锁操作
🔍 3. 关键原则
场景 | 操作 | 原因 |
---|---|---|
基本赋值 operator= | 必须返回 Widget& | 支持 a=b=c 连锁赋值 |
复合赋值 operator+= 等 | 同样返回 Widget& | 保持与基本赋值一致的行为 |
避免返回 const Widget& | 返回非const引用 | 允许 (a=b).doSomething() 链式调用 |
继承体系中的赋值操作符 | 调用基类赋值操作符并返回自身引用 | 确保基类部分正确赋值 |
⚠️ 4. 错误案例:返回临时对象
class Widget {
public:Widget operator=(const Widget& rhs) { // 错误:返回值而非引用return Widget(rhs.value); // 返回临时对象副本}
};// 使用:
a = b = c; // 编译通过但行为错误:
// b=c 返回临时对象,a 被赋值为临时对象而非c
后果:
- 产生额外临时对象(性能损失)
a
最终获得c
的副本,但b
未被修改- 违反 “a=b” 应修改 b 的预期
💎 总结:赋值操作符三原则
-
返回 *this 引用
所有赋值操作符必须返回当前对象的非const引用:class MyClass { public:MyClass& operator=(const MyClass& rhs) {// ... 赋值操作return *this;} };
-
保持连锁赋值语义
确保支持x=y=z
语法,行为等价于:y = z; x = y;
-
兼容内置类型行为
赋值表达式结果应为左值(可继续被赋值):(a = b) = c; // 应合法:a被赋值为c