当前位置: 首页 > news >正文

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 的预期

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

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

    class MyClass {
    public:MyClass& operator=(const MyClass& rhs) {// ... 赋值操作return *this;}
    };
    
  2. 保持连锁赋值语义
    确保支持 x=y=z 语法,行为等价于:

    y = z;
    x = y;
    
  3. 兼容内置类型行为
    赋值表达式结果应为左值(可继续被赋值):

    (a = b) = c; // 应合法:a被赋值为c
    
http://www.lryc.cn/news/603422.html

相关文章:

  • 【Java面试题】面向对象
  • Kubernetes 高级调度 01
  • 实现多路标注截图
  • WMS仓储管理系统在不良品管理中的优化策略
  • OpenCL - study - code04 canny
  • C++基础:模拟实现priority_queue(堆),详细介绍仿函数
  • Python 程序设计讲义(29):字符串的处理方法——大小写转换
  • 网络数据传输与NAT技术的工作原理
  • 计算机网络五层模型
  • 【微信小程序】12、生物认证能力
  • .gitignore 添加 vue.config.js 时不好使
  • 微信小程序无法构建npm,可能是如下几个原因
  • Excel批量加密工具,一键保护多个文件
  • 聚观早报 | 三星获特斯拉AI芯片订单;小米16首发成安卓最强SOC;iPhone 17 Pro支持8倍光学变焦
  • 递归推理树(RR-Tree)系统:构建认知推理的骨架结构
  • [leetcode] 实现 Trie (前缀树)
  • 开发避坑短篇(8):Java Cookie值非法字符异常分析与解决方案:IllegalArgumentException[32]
  • 【C#获取高精度时间】
  • 智能落地扇方案:青稞RISC-V电机 MCU一览
  • SZU大学物理实验报告|电位差计
  • 【dropdown组件填坑指南】—怎么实现下拉框的位置计算
  • python cli命令 cli工具命令 自定义cli命名 开发 兼容 window、mac、linux,调用示例
  • React面试题目和答案大全
  • 注册发送手机短信
  • Linux 完整删除 Systemd 服务的步骤
  • 【自制组件库】从零到一实现属于自己的 Vue3 组件库!!!
  • Rust 实战三 | HTTP 服务开发及 Web 框架推荐
  • leaflet中绘制轨迹线的大量轨迹点,解决大量 marker 绑定 tooltip 同时显示导致的性能问题
  • HTTP 与 HTTPS 的区别
  • div 封装日历