拷贝构造函数

拷贝构造函数的概念

   1. 只有单个形参,该形参是对本类类型对象的引用(一般常用 const 修饰),

在用已存在的类类型对象创建新对象时由编译器自动调用。

   2.C++ 会为类生成一个默认拷贝构造函数赋值操作符。这两个默认实现的行为都是逐位复制(即浅拷贝),它只是简单地复制每个成员的值,包括指针的地址,而不分配新的内存空间。

拷贝构造函数的特性

它也是一个特殊的成员函数,所以他符合构造函数的一些特性:

① 拷贝构造函数是构造函数的一个重载形式。函数名和类名相同,没有返回值。

② 拷贝构造函数的参数只有一个,并且 必须要使用引用传参!

 深拷贝 构造函数来替换掉程序中的 浅拷贝构造函数。

拷贝构造函数启动规则

	类名 对象1
启动规则如下:
	类名 对象2(对象1)
	类名 对象2 = 对象1
	类名 * 对象2 = new 类名(对象1)

格式

类名(const 类名 & other)

需要编写拷贝构造函数的原因

    使用 编译器提供的

     拷贝构造函数 以及 赋值运算符    会将指针指向的空间也赋值过去

深拷贝  自己写

浅拷贝  使用 编译器提供的

 浅拷贝

浅拷贝只是简单地将对象的值(包括指针的地址)赋值给新的对象。对于指针成员,浅拷贝只是复制指针本身,而不会为指针指向的动态内存分配新的空间。这意味着两个对象中的指针将指向同一块内存。

浅拷贝的风险

如果两个对象都指向同一块内存,当其中一个对象修改这块内存时,另一个对象也会受到影响。此外,当对象被销毁时,如果两个对象都尝试释放同一块内存,就会导致 双重释放(double deletion)错误,程序可能崩溃

#include <iostream>
 
class Date {
public:
    Date(int year = 0, int month = 1, int day = 1) {
        _year = year;
        _month = month;
        _day = day;
    }
 
    /* Date d2(d1); */
    Date(Date& d) {         // 这里要用引用,否则就会无穷递归下去
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
    void Print() {
        printf("%d-%d-%d\n", _year, _month, _day);
    }
 
private:
    int _year;
    int _month;
    int _day;
};
 
int main(void)
{
    Date d1(2022, 3, 9);
    Date d2(d1);          // 拷贝复制
 
    // 看看拷贝成功没
    d1.Print();
    d2.Print();
 
    return 0;
}

深拷贝、

是为指针成员分配新的内存空间,并复制原对象中的数据到新的内存。这保证了每个对象都有自己独立的一份数据,不会共享同一块内存,因此也不会引发双重释放的问题。

#include <iostream>
#include <cstring>

class Date {
public:
    Date(int year = 0, int month = 1, int day = 1, const char* desc = "") {
        _year = year;
        _month = month;
        _day = day;
        _desc = new char[strlen(desc) + 1];  // 分配内存
        strcpy(_desc, desc);  // 复制描述字符串
    }

    // 深拷贝构造函数
    Date(const Date& d) {
        _year = d._year;
        _month = d._month;
        _day = d._day;
        _desc = new char[strlen(d._desc) + 1];  // 分配内存
        strcpy(_desc, d._desc);  // 复制描述字符串
    }

    // 析构函数,释放动态内存
    ~Date() {
        delete[] _desc;  // 释放内存
    }

    void Print() const {
        printf("%d-%d-%d: %s\n", _year, _month, _day, _desc);
    }

private:
    int _year;
    int _month;
    int _day;
    char* _desc;  // 日期描述字符串
};

int main(void)
{
    Date d1(2022, 3, 9, "Important date");
    Date d2(d1);  // 深拷贝构造

    // 查看两个对象是否完全独立
    d1.Print();
    d2.Print();

    return 0;
}

注意

深拷贝和浅拷贝的区别

浅拷贝:

如果类中没有显性的定义拷贝构造函数,编译器会提供一个默认的拷贝构造函数,这个默认的拷贝构造函数,只完成成员之间的简单赋值。如果类中没有指针成员,只用这个默认的拷贝构造函数,是没有问题的。

深拷贝:

如果类中有指针成员,并且使用浅拷贝,指针成员之间也是只做了简单的赋值。相当于两个对象的指针

 在C++中,当你定义了一个空类时,编译器会默认生成哪些函数?请写出它们的声明格式。

class Test {};  // 定义了一个空类Test

// 编译器默认生成的函数如下:

// 1. 默认构造函数:
Test(void);

// 2. 拷贝构造函数:
Test(const Test &other);

// 3. 析构函数:
~Test(void);

// 4. 拷贝赋值运算符:
const Test &operator=(const Test &other);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值