这是我从这里看到的一个面试问题:http: //www.careercup.com/question?id=1707701
想知道更多关于这个。谢谢
当您拥有“远程所有权”时,浅拷贝会(主要)导致问题。最常见的形式是指向对象拥有的数据的指针,因此当对象被销毁时,它拥有的数据也会被销毁。许多人遇到的一个地方是不可避免的字符串类:
// 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
,指针会被复制,但它指向的内容不会被复制。我们有两个对象都包含指向同一个缓冲区的指针。当其中一个被销毁时,它会删除数据的关联缓冲区。然后我们有一个悬空指针——它仍在尝试引用缓冲区,但缓冲区不再存在。当第二个对象被销毁时,它会尝试再次释放相同的内存——但由于它已经被释放,这会导致未定义的行为(即,任何事情都可能发生,而且通常会发生不好的事情)。
浅拷贝有两种常见的替代方法。一种是“深”拷贝,我们为类重载了拷贝构造函数和赋值运算符,在它们中当我们拷贝/赋值对象时,我们分配一个新的缓冲区并将旧缓冲区的内容复制到新的缓冲区中.
第二个是引用计数。代替指向缓冲区的“原始”指针,我们使用指向缓冲区的“智能”指针。智能指针跟踪有多少对象引用了缓冲区,并且只有在没有任何内容引用它时才释放缓冲区本身。
两者都不是完美的:深度复制可能会很慢并且会占用大量内存,尤其是在涉及大量数据的情况下。在多线程环境中引用计数可能会很慢——因为引用计数可以从多个线程访问,你必须保护它以确保一次只有一个线程修改它(这通常比一个线程慢一个数量级)正常递增/递减)。
浅拷贝是当你只复制一个具有完全相同的字段(和指针)的对象时:
班上
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
这是带有图像的解释
维基百科有很好的介绍