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
相关推荐
玖笙&1 小时前
✨WPF编程基础【3.3】:容器控件(附源码)
c++·wpf·visual studio
汉克老师1 小时前
GESP5级C++考试语法知识(十七、二分算法提高篇(二))
c++·算法·二分算法·gesp5级·gesp五级·二分算法易错点
我材不敲代码2 小时前
Python 正则表达式进阶实战:从文本清洗到复杂信息提取
c++·python·正则表达式
我命由我123452 小时前
Android Framework P3 - MediaServer 进程、认识 ServiceManager 进程
android·c语言·开发语言·c++·visualstudio·visual studio·android runtime
计算机安禾2 小时前
【c++面向对象编程】第48篇:Lambda表达式与std::function:OOP中的函数式编程
java·c++·算法
chxin140162 小时前
CMake 笔记
c++
C+-C资深大佬3 小时前
在C++中,const和#define有什么区别?
开发语言·c++
春蕾夏荷_7282977254 小时前
MFC 简易成绩管理界面
c++·mfc·成绩
weixin_421725265 小时前
C语言、C++与C#深度研究报告:从底层控制到现代企业级开发的演进
c语言·c++·c·内存管理·编译模型
basketball6165 小时前
C++ 多态完全指南:同一个接口,千变万化的行为
java·开发语言·c++