浅拷贝有哪些问题?

发布于 2024-10-21 16:54:25 字数 164 浏览 1 评论 0原文

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

想要了解更多关于这个。谢谢

This is an interview question I saw from here:
http://www.careercup.com/question?id=1707701

Want to know more about this .thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无声情话 2024-10-28 16:54:25

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

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

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

第二个是引用计数。我们使用指向缓冲区的“智能”指针,而不是指向缓冲区的“原始”指针。智能指针会跟踪有多少对象引用该缓冲区,并且仅当不再有任何对象引用该缓冲区时才释放缓冲区本身。

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

Shallow copy causes a problem (primarily) when you have "remote ownership". The most common form is a pointer to data that's owned by the object so when the object is destroyed the data it owns gets destroyed as well. One place many people run into this is the inevitable string class:

// 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;
}

This will compile just fine. Under these exact circumstances, it might even seem to run fine as well. That doesn't mean it's really right though. When we assign s to t, the pointer gets copied, but what it points at does not get copied. We have two objects both containing pointers to the same buffer. When one of them gets destroyed, it deletes the associated buffer for the data. Then we have a dangling pointer -- it's still trying to refer to the buffer, but the buffer no longer exists. When the second object gets destroyed, it'll try to free the same memory again -- but since it's already been freed, that leads to undefined behavior (I.e., anything can happen, and something bad usually will).

There are two common alternatives to shallow copying. One is a "deep" copy, in which we overload the copy constructor and assignment operator for the class, and in them when we copy/assign the object, we allocate a new buffer and copy the contents of the old buffer to the new one.

The second is reference counting. Instead of a "raw" pointer to the buffer, we use a "smart" pointer to the buffer. The smart pointer keeps track of how many objects refer to the buffer and only frees the buffer itself when nothing refers to it any more.

Neither is entirely perfect: deep copying can be slow and use a lot of memory, especially if there's a lot of data involved. Reference counting can be slow in multi-threaded environments -- since the reference count can be accessed from multiple threads, you have to protect it to assure only one thread modifies it a time (which is usually at least an order of magnitude slower than a normal increment/decrement).

心在旅行 2024-10-28 16:54:25

浅复制是指您仅复制具有完全相同的字段(和指针)的对象:

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

这里是带有图像的解释

shallow copy is when you just make a copy of an object with exactly the same fields(and pointer):

the class

class Car{
String name;
Owner* owner;
}

arguments:

Owner owner
Car car1 = {"car", owner}
Car car2 = car1.copy
car2 = {"car", owner}

so now we copied all fields of car1 to car2 and both of them fields owner pointing to same owner, and since owner it's a pointer we are now have a dangling pointer so each change made in car1 will affect car2

but if we would made a deep copy we should get it right:

Car car3 = car1.deepCopy => will create ownerCopy = owner.copy
car3 = {"car", ownerCopy}

so now changes on car1 won't affect car3 at all

HERE is an explanation with images

泅渡 2024-10-28 16:54:25

维基百科有很好的介绍

Wikipedia has a good introduction

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文