可能重复:
What is the difference between a deep copy and a shallow copy?
深拷贝和浅拷贝之间有什么区别。复制构造函数的副本是什么类型的?
答案 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中的值。反之亦然。浅拷贝的情况有所不同,因为只复制了引用,因此,在复制的对象中更改此字段会影响原始对象。
复制构造函数的副本是什么类型的?
这是依赖于实现的。这意味着没有严格的规则,你可以像深拷贝或浅拷贝那样实现它,但据我所知,在拷贝构造函数中实现深拷贝是一种常见的做法。默认复制构造函数执行浅拷贝。