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

从浅拷贝到深拷贝:C++赋值运算符重载的核心技术

目录

一、赋值运算符重载的核心特性

1、成员函数重载

2、编译器默认生成

3、实现注意事项

二、何时需要自定义赋值运算符重载

重要原则

三、代码示例讲解

拷贝构造与赋值运算符的区别

关键要点

1. 参数类型设置为引用并用const修饰

2. 返回值使用引用

3. 自赋值检查

4. 编译器生成的默认赋值运算符

四、何时需要自定义赋值运算符


        赋值运算符重载是C++中一个重要的默认成员函数,用于在两个已经存在的对象之间进行拷贝赋值。它与拷贝构造函数有本质区别:拷贝构造函数是用一个已存在的对象来初始化一个新创建的对象,而赋值运算符重载则是在两个已存在的对象之间进行赋值操作。

一、赋值运算符重载的核心特性

1、成员函数重载

  • 赋值运算符必须重载为类的成员函数

  • 参数建议使用const 类类型&,避免不必要的拷贝构造

  • 返回类型建议使用类类型&,支持连续赋值并提高效率

2、编译器默认生成

  • 若未显式实现,编译器会自动生成默认赋值运算符重载

  • 默认实现行为:

    • 对内置类型成员:值拷贝/浅拷贝(逐字节复制)

    • 对自定义类型成员:调用其默认生成的赋值运算符重载

3、实现注意事项

  • 需要检查自赋值情况(if(this != &d)

  • 应返回*this以支持连续赋值

  • 返回值类型为引用以减少拷贝开销


二、何时需要自定义赋值运算符重载

类类型是否需要自定义原因
Date类(全内置类型)编译器生成的浅拷贝已足够
Stack类(管理资源)需要实现深拷贝
MyQueue类(含自定义类型成员)自动调用成员的赋值运算符

重要原则

        如果一个类需要显式实现析构函数来释放资源,那么它通常也需要显式实现赋值运算符重载。


三、代码示例讲解

class Date {
public:Date(int year = 1, int month = 1, int day = 1) : _year(year), _month(month), _day(day) {}// 拷贝构造函数Date(const Date& d) {cout << "Date(const Date& d)" << endl;_year = d._year;_month = d._month;_day = d._day;}// 赋值运算符重载Date& operator=(const Date& d) {// 检查自赋值if (this != &d) {_year = d._year;_month = d._month;_day = d._day;}return *this;  // 支持连续赋值}void Print() {cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main() {Date d1(2024, 7, 5);  // 构造函数Date d2(d1);          // 拷贝构造函数Date d3(2024, 7, 6);  d1 = d3;              // 赋值运算符重载// 注意:这是拷贝构造,不是赋值重载Date d4 = d1;         return 0;
}

拷贝构造与赋值运算符的区别

Date d1(2024, 1, 1);  // 构造函数
Date d2 = d1;         // 拷贝构造函数(创建新对象)
Date d3;              
d3 = d1;              // 赋值运算符重载(两个已存在对象)
  • 拷贝构造函数:用一个已存在的对象初始化一个新创建的对象

  • 赋值运算符:在两个已存在的对象之间进行赋值操作

关键要点

1. 参数类型设置为引用并用const修饰

  • 赋值运算符重载函数的第一个形参是隐式的this指针,第二个形参是赋值运算符的右操作数

  • 使用引用传参避免不必要的拷贝构造调用

  • 添加const修饰确保不会修改右操作数,同时保持常性,不会造成权限放大

2. 返回值使用引用

  • 为了支持连续赋值(如d3 = d2 = d1),需要返回赋值后的左操作数

  • 返回引用避免不必要的拷贝

  • 返回*this因为this指针指向的就是左操作数

3. 自赋值检查

  • 在赋值前检查是否是自赋值(如d1 = d1

  • 避免不必要的操作,同时也是防御性编程的重要部分

4. 编译器生成的默认赋值运算符

  • 如果类没有显式定义赋值运算符重载,编译器会自动生成一个

  • 默认实现是按字节序的值拷贝(浅拷贝)

  • 对于简单类(如日期类)通常足够,但对于管理资源的类需要自定义


四、何时需要自定义赋值运算符

当类满足以下条件之一时,通常需要自定义赋值运算符:

  1. 类包含指针成员并管理动态内存

  2. 类需要深拷贝语义

  3. 类有需要特殊处理的资源(如文件句柄、网络连接等)

  4. 类有需要保持唯一性的成员(如ID)

对于简单的值类(如日期类),编译器生成的默认赋值运算符通常就足够了。

        理解赋值运算符重载与拷贝构造函数的区别对掌握C++对象模型至关重要。对于管理资源的类,正确的实现赋值运算符重载可以避免内存泄漏和重复释放等问题。

http://www.lryc.cn/news/613971.html

相关文章:

  • 【设计模式】抽象工厂模式 (工具(Kit)模式)
  • 【接口自动化】-2- request模块及通过变量实现接口关联
  • 瑞利杂波背景下不同环境的虚警概率与目标检测概率仿真
  • 项目历程—右键菜单(问题,解决,拓展(非教学向,因为乱))
  • django uwsgi启动报错failed to get the Python codec of the filesystem encoding
  • 17.14 CogVLM-17B多模态模型爆肝部署:4-bit量化+1120px高清输入,A100实战避坑指南
  • 流形折叠与条件机制
  • 【ee类保研面试】其他类---计算机网络
  • STM32HAL 快速入门(二):用 CubeMX 配置点灯程序 —— 从工程生成到 LED 闪烁
  • 如何在Vue中使用拓扑图功能
  • 相机坐标系与世界坐标系的点相互转换:原理、可视化与实践
  • HTML 与 CSS:从 “认识标签” 到 “美化页面” 的入门指南
  • Numpy科学计算与数据分析:Numpy数据分析与图像处理入门
  • 使用Python提取PDF大纲(书签)完整指南
  • Date、Calendar、LocalDateTime:Java 处理时间的类该怎么选?
  • 【网络自动化】利用Python脚本与计划任务,实现H3C/HPE设备配置无人值守备份
  • 安装向量数据库chromadb
  • Java+uniapp+websocket实现实时聊天,并保存聊天记录
  • mac笔记本如何重新设置ssh key
  • React Hooks 完全指南:从概念到内置 Hooks 全解析
  • 五种IO模型与⾮阻塞IO
  • leetcode1456:定长子串中元音的最大数目(定长滑动窗口)
  • 云平台运维工具 —— 阿里云原生工具
  • 云原生时代的 Linux:容器、虚拟化与分布式的基石
  • react的form.resetFields()
  • 人工智能之数学基础:事件独立性
  • Java中重写和重载有哪些区别
  • MySQL vs PostgreSQL 深度对比:为你的新项目选择正确的开源数据库 (2025)
  • LVS高可靠
  • Java-注解