一段代码背后的思考

#include <bits/stdc++.h>
#include <iostream>

using namespace std;

class A
{
private:
    int *p;
public:

    A()
    {

    }
    int * ini()
    {
        p = new int[8];
        p[0] = 12;
        return p;
    }
    int show()
    {
        cout << p[0] << endl;
        return 0;
    }
    ~A()
    {
        delete[] p;
    }
};

int main(){
    A a2;
    {
        A a1;
        a1.ini();
        a1.show();
        a2 = a1;
    }

    a2.show();

    return 0;
}

运行结果

上图是代码的运行结果,为什么两次的p[0]结果不一样呢?而且第二次的p[0]的值是一个随机数。

其实熟悉c++的同学已经发现了,这是由于浅拷贝的原因造成的,改正的方法就是换成深拷贝,重载赋值运算符。

那么什么是浅拷贝和深拷贝呢?

就用上述代码 作为例子,我们可以看到类中有一个指针变量的成员p,且该指针指向堆上分配的空间。当我们在做对象之间的赋值时,就会调用默认的赋值运算符,然而默认的赋值运算符是一个浅拷贝,浅拷贝只是让被赋值的对象中的p和赋值对象中的p指向了同一片区域(即a2.p = a1.p),然而赋值对象在析构时就把p指向的区域释放掉了,所以第二次输出的p[0]就是一个随机数,而不是12。

那么深拷贝是如何解决这个问题的呢?

其实很简单,我们在重载赋值运算符时重新开辟一段区域,并把复制对象中对应的区域复制过来,并把p指向这个区域,这样就是一个深拷贝的过程,即使原来的区域被释放掉,任然可以输出12,从而达到我们的预期目的。具体代码如下:

A & operator = (A & a)
{
    p = new int[8];
    memcpy(p, a.p, sizeof(p));//深拷贝
    return *this;
}

除了a2 = a1这种赋值形式,还有一种情况 A a2 = a1这种赋值形式,而这种赋值形式就不是调用赋值运算符了,而是调用拷贝构造函数,那么相应的就是把深拷贝做到拷贝构造函数里了。

这里写图片描述

总结:一般,如果需要手动编写析构函数的类,都需要overload 拷贝构造函数和赋值运算符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值