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
相关推荐
charlie1145141914 小时前
设计自己的小传输协议 导论与概念
c++·笔记·qt·网络协议·设计·通信协议
程序员编程指南7 小时前
Qt 并行计算框架与应用
c语言·数据库·c++·qt·系统架构
努力的小帅8 小时前
C++_红黑树树
开发语言·数据结构·c++·学习·算法·红黑树
CN-Dust8 小时前
【C++】指针
开发语言·c++
逐花归海.9 小时前
『 C++ 入门到放弃 』- 哈希表
数据结构·c++·程序人生·哈希算法·散列表
筏.k9 小时前
C++现代Redis客户端库redis-plus-plus详解
c++·redis
程序员编程指南9 小时前
Qt 多线程调试技巧与常见问题
c语言·开发语言·c++·qt
徐归阳10 小时前
第十一天:不定方程求解
c++·visual studio
1白天的黑夜110 小时前
前缀和-974.和可被k整除的子数组-力扣(LeetCode)
c++·leetcode·前缀和
春日轻轨@10 小时前
SPFA检测负权环
数据结构·c++·算法