Effective C++ 条款10:令operator=返回一个reference to *this

Effective C++ 条款10:令operator=返回一个reference to *this


核心思想 :赋值操作符(operator=)应始终返回当前对象的引用(*this),以实现连锁赋值并保持与内置类型一致的语义。

⚠️ 1. 问题场景:违反连锁赋值语义
cpp 复制代码
class Widget {
public:
    void operator=(const Widget& rhs) { // 错误:返回void
        value = rhs.value;
    }
private:
    int value;
};

int main() {
    Widget a, b, c;
    a = b = c; // 错误:void类型不能作为右值
    return 0;
}

结果

  • 编译错误:void 类型不能用于赋值操作
  • 破坏与内置类型(如int)一致的赋值语义

✅ 2. 解决方案:返回 *this 引用
(1) 标准赋值操作符实现 (⭐️必须)
cpp 复制代码
class Widget {
public:
    Widget& operator=(const Widget& rhs) { // 返回当前对象引用
        if (this != &rhs) {               // 自赋值检查(条款11)
            value = rhs.value;
        }
        return *this; // 关键:返回 *this
    }
private:
    int value;
};
(2) 复合赋值操作符实现(+=, -=等)
cpp 复制代码
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. 错误案例:返回临时对象
cpp 复制代码
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 的预期

💎 总结:赋值操作符三原则

  1. 返回 *this 引用

    所有赋值操作符必须返回当前对象的非const引用:

    cpp 复制代码
    class MyClass {
    public:
        MyClass& operator=(const MyClass& rhs) {
            // ... 赋值操作
            return *this;
        }
    };
  2. 保持连锁赋值语义

    确保支持 x=y=z 语法,行为等价于:

    cpp 复制代码
    y = z;
    x = y;
  3. 兼容内置类型行为

    赋值表达式结果应为左值(可继续被赋值):

    cpp 复制代码
    (a = b) = c; // 应合法:a被赋值为c
相关推荐
mjhcsp16 分钟前
C++ KMP 算法:原理、实现与应用全解析
java·c++·算法·kmp
好大哥呀20 分钟前
C++ IDE
开发语言·c++·ide
WW_千谷山4_sch31 分钟前
MYOJ_10599:CSP初赛题单10:计算机网络
c++·计算机网络·算法
梵尔纳多1 小时前
绘制一个矩形
c++·图形渲染·opengl
橘颂TA1 小时前
【剑斩OFFER】算法的暴力美学——leetCode 946 题:验证栈序列
c++·算法·leetcode·职场和发展·结构与算法
闻缺陷则喜何志丹1 小时前
【状态机动态规划】3686. 稳定子序列的数量|1969
c++·算法·动态规划·力扣·状态机动态规划
liulilittle1 小时前
OPENPPP2 网络驱动模式
开发语言·网络·c++·网络协议·信息与通信·通信
mjhcsp1 小时前
C++ AC 自动机:原理、实现与应用全解析
java·开发语言·c++·ac 自动机
爱吃生蚝的于勒2 小时前
【Linux】进程间通信之匿名管道
linux·运维·服务器·c语言·数据结构·c++·vim
wanderist.2 小时前
C++输入输出的一些问题
开发语言·c++·图论