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
相关推荐
倒头就睡的小比特2 天前
算法竞赛C++常用的STL
c++·算法
weilx12342 天前
C++笔记-文件IO-<fcntl.h>
c++
Smileyqp沛沛2 天前
前端?C++ ?较大差异基础罗列
c++·基础·前端转c++
C语言小火车2 天前
C/C++ 为什么需要编译器?
开发语言·c++
旖旎夜光2 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
吞下星星的少年·-·2 天前
C++ 萌新语法入门篇
c++·算法比赛
霍霍的袁2 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
another heaven2 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
程序猿编码2 天前
告别改源码适配模型:纯 C++ 可配置 LLM 推理引擎,全格式全结构兼容
c++·大模型·llm·推理引擎
此生决int2 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++