深拷贝vs浅拷贝
可能重复:
深拷贝和浅拷贝之间有什么区别?
深浅拷贝有什么区别? 拷贝构造函数做什么types的拷贝?
浅拷贝:
该副本的一些成员可能会引用与原始相同的对象:
class X { private: int i; int *pi; public: X() : pi(new int) { } X(const X& copy) // <-- copy ctor : i(copy.i), pi(copy.pi) { } };
在这里,原始和复制的X
对象的pi
成员都将指向相同的int
。
深拷贝:
原始的所有成员都被克隆(如果需要,recursion地)。 没有共享对象:
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! { } };
在这里,原始和复制的X
对象的pi
成员将指向不同的int
对象,但这两个都具有相同的值。
默认的复制构造函数(如果您自己不提供自动提供的)将只创build浅拷贝。
更正:下面的几个注释已经正确地指出,说默认的拷贝构造函数总是执行浅拷贝(或者深层拷贝)是错误的。 一个types的拷贝构造函数是创build一个浅拷贝还是深拷贝, 还是两者之间的内容都取决于每个成员拷贝行为的组合; 毕竟,一个成员的types的拷贝构造函数可以做任何想做的事情。
以上是关于上述代码示例的1998年C ++标准第12.8节第8节:
类
X
的隐式定义的拷贝构造函数执行其子对象的成员拷贝。 […]每个子对象都以适合其types的方式复制:[…]如果子对象是标量types,则使用内置赋值运算符。
这个典型的例子是指向结构或对象的指针数组(可变)。
浅拷贝复制数组并保持对原始对象的引用。
深拷贝将复制(克隆)这些对象,因此它们与原始文件无关。 隐含在这个对象本身被深拷贝。 这是困难的地方,因为没有真正的方法可以知道是否被深拷贝了。
复制构造函数用于初始化具有相同类的以前创build的对象的新对象。 默认情况下编译器写了一个浅拷贝。 浅拷贝工作正常,当dynamic内存分配不涉及,因为当涉及dynamic内存分配时,两个对象将指向一个堆中相同的内存位置。因此,为了消除这个问题,我们写了深拷贝,所以两个对象都有自己的属性副本在记忆中。
为了阅读完整的例子和解释的细节,你可以看到文章构造和析构函数 。
默认的复制构造函数很浅。 您可以根据需要制作自己的复制构造函数。 请参阅C ++注释:OOP:复制构造函数 。
深层复制从字面上执行深层复制。 这意味着,如果你的类有一些引用的字段,它们的值将被复制,而不是引用自己。 例如,如果您有两个类的实例,A和B带有引用types的字段,并执行深度复制,则在A中更改该字段的值将不会影响B中的值,反之亦然。 事情与浅拷贝不同,因为只有引用被复制,因此,在复制对象中更改此字段会影响原始对象。
拷贝构造函数做什么types的拷贝?
它是依赖于实现的。 这意味着没有严格的规则,你可以像深拷贝或浅拷贝一样实现它,但据我所知,在拷贝构造函数中实现深层拷贝是一种常见的做法。 默认的拷贝构造函数虽然执行浅拷贝。