C++类的浅拷贝&深拷贝

发布时间:Dec. 29, 2022, 11:50 a.m.编辑:李佳生阅读(453)

假定我们有如下代码,定义了一个没有拷贝构造函数或重载等号的类。

class MyClass : {
public:
    Myclass() {ptr = new int();};
    ~MyClass() {delete ptr;};
    
    int *ptr = nullptr;
    int mem = 0;
};

int main() {
    MyClass c1;
    MyClass c2 = c1;
    MyClass c3(c1);
    MyClass c4;
    c4 = c1;
    return 0;
}

此时c2等号、c3初始化执行的是编译器默认的拷贝构造函数,c4执行的是编译器默认的等号操作,即大概发生如下动作

c2.mem = c1.mem;
c2.ptr = c1.ptr;

c3.mem = c1.mem;
c3.ptr = c1.ptr;

c4.mem = c1.mem;
c4.ptr = c1.ptr;

熟悉c/c++的同学此时就能看出问题,对于指针ptr,只传递了地址的数值,这就意味着c2、c3、c4的ptr指向与c1是一样的,虽然编译会通过,但是实际使用时会造成问题: c1 c2 c3 c4析构时,会重复释放相同地址的内存,产生问题。

正确的方法应该是定义拷贝构造函数和重载等号,执行内容的深拷贝,这样成员指针就是地址不同,但是内容相同的内存了,也不会产生上述问题。

class MyClass : {
public:
    Myclass() {ptr = new int[10]();};
    ~MyClass() {delete[] ptr;};
    MyClass(const MyClass& c) {
        mem = c.mem;
        ptr = new int();
        *ptr = *c.ptr;
    }
    Myclass& operator=(Myclass& c) {
        if (this != &c) {
            mem = c.mem;
            ptr = new int();
            *ptr = *c.ptr;
        }
        return *this;
    }
    
    int *ptr = nullptr;
    int mem = 0;
};


关键字Coding C/C++