这是我从这里看到的一个面试问题: http://www.careercup.com/question?id=1707701
想要了解更多信息。谢谢
答案 0 :(得分:7)
当您拥有“远程所有权”时,浅拷贝会导致问题(主要是)。最常见的形式是指向对象拥有的数据的指针,因此当对象被销毁时,它拥有的数据也会被销毁。许多人遇到的一个地方是不可避免的字符串类:
// warning: bad code. Do *not* use.
class mystring {
char *data;
public:
mystring() : data(NULL) {}
mystring(char *init) {
data = new char[strlen(init)+1];
strcpy(data, init);
}
~mystring() { delete [] data; }
};
int main() {
mystring s("This is a string");
mystring t;
t = s;
}
这将编译得很好。在这些完全的情况下,可能甚至似乎也运行正常。这并不意味着它确实是对的。当我们将s
分配给t
时,指针会被复制,但它指向的内容不会被复制。我们有两个对象,它们都包含指向同一缓冲区的指针。当其中一个被破坏时,它会删除数据的相关缓冲区。然后我们有一个悬空指针 - 它仍然试图引用缓冲区,但缓冲区不再存在。当第二个对象被破坏时,它会尝试再次释放相同的内存 - 但由于它已经被释放,这会导致未定义的行为(即,任何事情都可能发生,通常会发生一些不好的事情)。
浅层复制有两种常见的替代方法。一个是“深度”副本,其中我们重载类的复制构造函数和赋值运算符,当我们复制/分配对象时,我们分配一个新缓冲区并将旧缓冲区的内容复制到新缓冲区
第二个是引用计数。我们使用指向缓冲区的“智能”指针而不是指向缓冲区的“原始”指针。智能指针跟踪有多少对象引用缓冲区,并且只有在没有任何引用时才释放缓冲区本身。
两者都不是完全完美的:深度复制可能很慢并且占用大量内存,尤其是涉及大量数据时。在多线程环境中引用计数可能很慢 - 因为可以从多个线程访问引用计数,所以必须保护它以确保只有一个线程一次修改它(通常至少比一个线程慢一个数量级)正常增量/减量)。
答案 1 :(得分:4)
浅层复制是指您只使用完全相同的字段(和指针)制作对象的副本:
班级
class Car{
String name;
Owner* owner;
}
参数:
Owner owner
Car car1 = {"car", owner}
Car car2 = car1.copy
car2 = {"car", owner}
所以现在我们将car1的所有字段复制到car2,并且它们都指向同一所有者的字段所有者,并且由于所有者它是一个指针,我们现在有一个悬空指针,因此在car1中进行的每次更改都会影响car2
但是如果我们做了深刻的复制,我们应该做对:
Car car3 = car1.deepCopy => will create ownerCopy = owner.copy
car3 = {"car", ownerCopy}
所以现在对car1的更改不会影响car3
HERE是对图片的解释
答案 2 :(得分:3)
Wikipedia有一个很好的介绍