[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. 编译器自动生成的已经足够使用
相关推荐
Ada's3 小时前
【计算机基础系列】003:Python数据结构
开发语言·数据结构·python
2601_962885723 小时前
如何用 Python 计算 TRIX 三重指数平滑均线指标?
开发语言·python
还卿一钵无情泪4 小时前
Unsloth 微调 构建自己的大模型 没有GPU也能微调
linux·开发语言·人工智能·python·大模型·nlp·unsloth
倔强的石头1065 小时前
应用账号最小权限实践:读写账号、报表账号、运维账号分层
java·运维·开发语言
传人once5 小时前
页面中心圆圈放大效果如何写
开发语言·javascript·ecmascript
NeilYuen5 小时前
【C++】STL源码仿写(二):vector
开发语言·c++
蜗牛互联网6 小时前
Python消费Responses SSE事件:增量文本、超时与取消
java·开发语言·人工智能·后端·python
郝学胜_神的一滴6 小时前
游戏引擎原理与实践 04:拆解引擎基础系统与内存管理
c++·游戏
All for pursuit.6 小时前
【设计-1】208.实现Trie (前缀树)
数据结构·c++·算法·leetcode
weixin_307779136 小时前
C++代码实现MATLAB中的crossval函数功能
开发语言·c++·算法·matlab