1

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

想知道更多关于这个。谢谢

4

3 回答 3

8

当您拥有“远程所有权”时,浅拷贝会(主要)导致问题。最常见的形式是指向对象拥有的数据的指针,因此当对象被销毁时,它拥有的数据也会被销毁。许多人遇到的一个地方是不可避免的字符串类:

// 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指针会被复制,但它指向的内容不会被复制。我们有两个对象都包含指向同一个缓冲区的指针。当其中一个被销毁时,它会删除数据的关联缓冲区。然后我们有一个悬空指针——它仍在尝试引用缓冲区,但缓冲区不再存在。当第二个对象被销毁时,它会尝试再次释放相同的内存——但由于它已经被释放,这会导致未定义的行为(即,任何事情都可能发生,而且通常会发生不好的事情)。

浅拷贝有两种常见的替代方法。一种是“深”拷贝,我们为类重载了拷贝构造函数和赋值运算符,在它们中当我们拷贝/赋值对象时,我们分配一个新的缓冲区并将旧缓冲区的内容复制到新的缓冲区中.

第二个是引用计数。代替指向缓冲区的“原始”指针,我们使用指向缓冲区的“智能”指针。智能指针跟踪有多少对象引用了缓冲区,并且只有在没有任何内容引用它时才释放缓冲区本身。

两者都不是完美的:深度复制可能会很慢并且会占用大量内存,尤其是在涉及大量数据的情况下。在多线程环境中引用计数可能会很慢——因为引用计数可以从多个线程访问,你必须保护它以确保一次只有一个线程修改它(这通常比一个线程慢一个数量级)正常递增/递减)。

于 2011-03-11T22:57:50.920 回答
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

是带有图像的解释

于 2011-03-11T22:36:54.713 回答
3

维基百科有很好的介绍

于 2011-03-11T22:29:35.513 回答