浅拷贝有什么问题?

时间:2011-03-11 22:27:15

标签: c++ shallow-copy

这是我从这里看到的一个面试问题: http://www.careercup.com/question?id=1707701

想要了解更多信息。谢谢

3 个答案:

答案 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有一个很好的介绍