深拷贝与浅拷贝

时间:2010-04-17 08:46:49

标签: c++ clone

  

可能重复:
  What is the difference between a deep copy and a shallow copy?

深拷贝和浅拷贝之间有什么区别。复制构造函数的副本是什么类型的?

3 个答案:

答案 0 :(得分:52)

浅拷贝:

副本的某些成员可能会引用与原始对象相同的对象:

class X
{
private:
    int i;
    int *pi;
public:
    X()
        : pi(new int)
    { }
    X(const X& copy)   // <-- copy ctor
        : i(copy.i), pi(copy.pi)
    { }
};

此处,原始且已复制的pi对象的X成员将指向同一int


深层复制:

原始的所有成员都被克隆(必要时递归)。没有共享对象:

class X
{
private:
    int i;
    int *pi;
public:
    X()
        : pi(new int)
    { }
    X(const X& copy)   // <-- copy ctor
        : i(copy.i), pi(new int(*copy.pi))  // <-- note this line in particular!
    { }
};

此处,原始和复制的pi对象的X成员将指向不同的int对象,但这两个对象具有相同的值。


默认的复制构造函数(如果您自己不提供,则自动提供)仅创建浅层副本。

  

更正:以下几条评论正确地指出,默认复制构造函数总是执行浅拷贝(或深拷贝,对于那个)是错误的物)。类型的复制构造函数是创建浅拷贝还是深拷贝,或两者之间的某些东西取决于每个成员的复制行为的组合;毕竟,成员的类型的复制构造函数可以做任何想做的事。

以下是1998年C ++标准第12.8节第8段关于上述代码示例的内容:

  

隐式定义的副本   类X的构造函数执行   其子对象的成员副本。   [...]每个子对象都被复制到   适合其类型的方式:[...]   [I] f子对象是标量类型,   内置赋值运算符是   使用。

答案 1 :(得分:12)

这个典型的例子是一个指向结构或对象的指针数组(可变)。

浅拷贝复制数组并维护对原始对象的引用。

深层复制也会复制(克隆)对象,因此它们与原始对象无关。隐含在这里的是对象本身被深层复制。这是它变得艰难的地方,因为没有真正的方法可以知道某些东西是否被深层复制。

复制构造函数用于使用先前创建的同一类对象初始化新对象。默认情况下编译器写了一个浅拷贝。当没有涉及动态内存分配时,浅拷贝工作正常,因为当涉及动态内存分配时,两个对象都将指向堆中的相同内存位置。因此,为了消除此问题,我们编写了深层副本,因此两个对象都有自己的属性副本在记忆中。

为了阅读完整示例和解释的详细信息,您可以看到文章Constructors and destructors

默认的复制构造函数很浅。您可以根据需要将自己的复制构造函数设置为深或浅。请参阅C++ Notes: OOP: Copy Constructors

答案 2 :(得分:3)

Deep copy字面上执行深层复制。这意味着,如果您的类有一些引用的字段,它们的值将被复制,而不是引用它们自己。例如,如果您有两个类的实例,A&amp; B具有引用类型的字段,并执行深度复制,在A中更改该字段的值不会影响B中的值。反之亦然。浅拷贝的情况有所不同,因为只复制了引用,因此,在复制的对象中更改此字段会影响原始对象。

  

复制构造函数的副本是什么类型的?

这是依赖于实现的。这意味着没有严格的规则,你可以像深拷贝或浅拷贝那样实现它,但据我所知,在拷贝构造函数中实现深拷贝是一种常见的做法。默认复制构造函数执行浅拷贝。