C++中的浅拷贝和深拷贝的区别

一般来说,创建一个对象的副本意味着创建一个具有相同字面价值、数据类型和资源的对象的精确副本。

  • 复制构造器
  • 默认的赋值运算符
// Copy Constructor
Object Obj1(Obj);
或者
Object Obj1 = Obj;

// Default assignment operator
Object Obj2;
Obj2 = Obj1;

根据对象所拥有的动态内存等资源,我们需要执行Shallow Copy或Deep Copy,以创建对象的副本。一般来说,如果一个对象的变量是动态分配的,那么就需要进行深度拷贝,以便创建一个对象的副本。

浅拷贝

在浅层拷贝中,通过简单地复制原始对象的所有变量的数据来创建一个对象。如果对象的变量都没有定义在内存的堆区,那么这个方法很好用。如果一些变量是从堆区动态分配的内存,那么复制的对象变量也将引用相同的内存位置。
这将产生模糊性和运行时错误,即悬空指针。由于两个对象都会引用相同的内存位置,那么一个对象的变化也会反映在另一个对象上。由于我们想要创建一个对象的副本,这个目的将不会被Shallow copy所填补。

注意:C++编译器隐含地创建了一个复制构造函数和重载赋值运算符,以便在编译时执行浅层复制。

示例代码:

// C++ program for the above approach
#include <iostream>
using namespace std;

// Box Class
class box {
private:
    int length;
    int breadth;
    int height;

public:
    // Function that sets the dimensions
    void set_dimensions(int length1, int breadth1,int height1)
    {
        length = length1;
        breadth = breadth1;
        height = height1;
    }

    void show_data()
    {
        cout << " Length = " << length
            << " Breadth = " << breadth
            << " Height = " << height
            << endl;
    }
};

// Driver Code
int main()
{
    // Object of class Box
    box B1, B3;

    // Set dimensions of Box B1
    B1.set_dimensions(214, 212, 216);
    B1.show_data();

    box B2 = B1;
    B2.show_data();

    B3 = B1;
    B3.show_data();

    return 0;
}

运行结果:

Length = 214
Breadth = 212
Height = 216
Length = 214
Breadth = 212
Height = 216
Length = 214
Breadth = 212
Height = 216

深复制

在深度复制中,通过复制所有变量的数据来创建一个对象,同时也为该对象分配相同价的类似内存资源。为了执行深度复制,我们需要明确地定义复制构造函数,如果需要的话,还需要分配动态内存。此外,还需要为其他构造函数中的变量动态分配内存。

示例代码:

#include <iostream>
using namespace std;

// Box Class
class box {
private:
    int length;
    int* breadth;
    int height;

public:
    // Constructor
    box()
    {
        breadth = new int;
    }

    void set_dimension(int len, int brea,
                    int heig)
    {
        length = len;
        *breadth = brea;
        height = heig;
    }

    // Function to show the dimensions
    // of the Box
    void show_data()
    {
        cout << "Length = " << length
            << "Breadth = " << *breadth
            << "Height = " << height
            << endl;
    }

    // Parameterized Constructors for
    // for implementing deep copy
    box(box& sample)
    {
        length = sample.length;
        breadth = new int;
        *breadth = *(sample.breadth);
        height = sample.height;
    }

    // Destructors
    ~box()
    {
        delete breadth;
    }
};

// Driver Code
int main()
{
    // Object of class first
    box first;

    // Set the dimensions
    first.set_dimension(212, 214, 216);

    // Display the dimensions
    first.show_data();

    box second = first;

    // Display the dimensions
    second.show_data();

    return 0;
}

运行结果:

Length = 212
Breadth = 214
Height = 216
Length = 212
Breadth = 214
Height = 216

让我们以表格的形式来看看其中的区别:

浅拷贝 深拷贝
1 当通过拷贝所有成员变量的数据来创建一个对象的副本时,它被称为浅度复制。 当通过复制另一个对象的数据以及位于该对象之外的内存资源的值来创建一个对象时,它被称为深度复制。
2 一个对象的浅拷贝复制了所有的成员字段值。 深拷贝是通过实现自己的拷贝构造函数来进行的。
3 在浅层拷贝中,两个对象不是独立的 它拷贝所有字段,并拷贝字段所指向的动态分配的内存
4 浅拷贝还创建了动态分配对象的副本 如果没有以正确的方式创建深度拷贝,那么副本将指向原始对象,这将带来灾难性的后果。