[C++] 拷贝构造还是赋值重载?类默认成员函数细节详解

C++98中类的默认成员函数有:默认构造函数、析构函数、拷贝构造函数,拷贝赋值,取地址重载

C++11新增了移动构造和移动赋值函数

1. 构造函数

可以参考作者早期发布的文章:

C++:构造函数与初始化列表详解

2. 析构函数

功能:清理释放对象中资源

特点:

  1. 函数名:~类名
  2. 无参数和返回值
  3. 未显式定义,会生成默认析构函数(内置类型:不处理;自定类型:另外调用
  4. 生命周期结束时自动调用
  5. 如果申请了资源,一定要自己显式写析构函数(否则会内存泄漏
  6. 析构顺序:后定义先析构(类似栈

使用示例:

cpp 复制代码
class MyBuffer {
public:
    MyBuffer()
    {
        this->data = new int[10]; 
        std::cout << "MyBuffer()" << std::endl;
    }

    ~MyBuffer()
    {
        delete[] this->data;  //显式实现资源释放
        std::cout << "~MyBuffer()" << std::endl;
    }

private:
    int* data;
};

3. 拷贝构造

功能:根据一个已存在对象构造一个相同的拷贝对象

特点:

  1. 构造函数的重载
  2. 第一个参数是类类型对象引用(传值调用拷贝构造,触发无穷递归调用
  3. 多参数:第一个外的参数必须有缺省值
  4. 自定类型对象进行拷贝时必须调用拷贝构造::即传参/传值都会触发
  5. 如果申请了资源,一定要显式写拷贝构造函数(内置类型:默认浅拷贝,析构时会多次delete同一份资源;自定类型:另外调用
cpp 复制代码
    // 拷贝构造函数:深拷贝
    MyBuffer(const MyBuffer& other)
    {
        this->data = new int[10]; //深拷贝
        for (int i = 0; i < 10; ++i)
        {
            this->data[i] = other.data[i];
        }
    }

结论:自定类型尽量传引用传参(传值触发拷贝构造->深拷贝->浪费内存

4. 运算符重载

功能:支持对象像普通变量一样使用各种运算符

特点 / 注意:

  1. 不能重载:.* :: sizeof ?: . 和语法中没有的符号(eg:@
  2. 函数名:operator运算符(参数数量和返回值类型由运算符本身特性决定
  3. 成员函数:第一个对象默认为this指针,不需要显式传(少一个参数
  4. 前置 / 后置运算符:后置运算符参数增加int形参,方便区分
  5. 重载>>和<<:必须为全局函数(第一个形参为ostream / istream

4.1 赋值重载

功能:支持已存在对象像普通变量一样赋值(区分拷贝构造

特点:

  1. 参数:const+引用,减少传值拷贝
  2. 返回值:类类型引用(减少拷贝 / 支持连续赋值
  3. 如果申请了资源,一定要显式写赋值重载(默认生成:内置类型浅拷贝;自定类型另外调用
  4. 赋值过程:检查自赋值->释放旧资源->申请新资源->拷贝
  5. 自赋值:释放自己的资源+重新访问拷贝,导致访问野指针
  6. 现代写法:传值传参,额外实现swap函数交换指针指向资源(不需要检查自赋值

使用示例:

cpp 复制代码
    MyBuffer& operator=(const MyBuffer& other)
    {
        if (this != &other) // 1. 检查自赋值
        {
            delete[] this->data;      // 2. 释放当前对象的旧资源
            this->data = new int[10]; // 3. 申请新的资源
            for (int i = 0; i < 10; ++i)
            {
                this->data[i] = other.data[i]; // 4. 拷贝数据
            }
        }
        return *this;
    }

现代写法:

cpp 复制代码
	void swap(...){//...}

    MyBuffer& operator=(MyBuffer other) //传值触发拷贝构造
    { 
        swap(*this, other); //交换指针指向对象
        return *this;
    }

4.2 取地址运算符重载

特点:

  1. 包括普通重载和const重载
  2. 编译器自动生成的已经足够使用
相关推荐
懂点Tech6 小时前
ctfshow misc28:GIF 高度修改解题与脚本实现
开发语言·windows·python
云和数据.ChenGuang6 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
美狐美颜SDK开放平台7 小时前
视频美颜SDK试用DEMO阶段应该测试什么?直播APP接入实操指南
开发语言·人工智能·深度学习·音视频·美颜sdk·直播美颜sdk·第三方美颜sdk
dtq04247 小时前
C++小案例 - 日志实战
开发语言·c++
星夜离尘568 小时前
MATLAB ADC 码流触顶诊断:命中数、缺口分段与削顶不可辨识性
开发语言·matlab
码匠许师傅8 小时前
【C++三方组件】Qt 概览:桌面 C++ 的事实标准与许可证三轨
开发语言·c++·qt
码匠许师傅9 小时前
【C++三方组件】POCO:跨平台系统编程全家桶
开发语言·c++
bkspiderx10 小时前
基于Socket的广播通信及C语言实现详解
c语言·开发语言·socket·广播·socket的广播通信
小王C语言10 小时前
Qt常用控件:输入类控件,单行/多行输入框、下拉框、(日期)微调框、旋钮、滑动条
开发语言·qt
ESDWAN10 小时前
SD-WAN 主备切换为什么仍然会断网?从检测机制到会话恢复分析
开发语言·php