我正在阅读 Scott Meyers “Effective C++”一书。有人提到有 tr1::shared_ptr
和 tr1::weak_ptr
就像内置指针一样,但它们会跟踪有多少 tr1::shared_ptr
指向一个对象。
这称为引用计数。这可以很好地防止非循环数据结构中的资源泄漏,但是如果两个或多个对象包含 tr1::shared_ptrs
从而形成一个循环,则该循环可能会使彼此的引用计数保持在零以上,即使当所有指向循环的外部指针都已被销毁。
这就是 tr1::weak_ptrs
的用武之地。
我的问题是循环数据结构如何使引用计数高于零。我请求一个示例 C++ 程序。 weak_ptrs
是如何解决问题的? (再次,请举例)。
最佳答案
让我重复你的问题:“我的问题,循环数据结构如何使引用计数高于零,请在 C++ 程序中举例说明。weak_ptrs
再次举例说明问题是如何解决的请。”
这样的 C++ 代码会出现问题(从概念上讲):
class A { shared_ptr<B> b; ... };
class B { shared_ptr<A> a; ... };
shared_ptr<A> x(new A); // +1
x->b = new B; // +1
x->b->a = x; // +1
// Ref count of 'x' is 2.
// Ref count of 'x->b' is 1.
// When 'x' leaves the scope, there will be a memory leak:
// 2 is decremented to 1, and so both ref counts will be 1.
// (Memory is deallocated only when ref count drops to 0)
回答您问题的第二部分:引用计数在数学上不可能处理循环。因此,weak_ptr
(基本上只是 shared_ptr
的精简版)不能用于解决循环问题——程序员正在解决循环问题。
为了解决这个问题,程序员需要知道对象之间的所有权关系,或者如果没有这种所有权自然存在,则需要发明一种所有权关系。
上面的C++代码可以改成A拥有B:
class A { shared_ptr<B> b; ... };
class B { weak_ptr<A> a; ... };
shared_ptr<A> x(new A); // +1
x->b = new B; // +1
x->b->a = x; // No +1 here
// Ref count of 'x' is 1.
// Ref count of 'x->b' is 1.
// When 'x' leaves the scope, its ref count will drop to 0.
// While destroying it, ref count of 'x->b' will drop to 0.
// So both A and B will be deallocated.
一个关键的问题是:weak_ptr
能否在程序员因权限不足或信息不足而无法分辨所有权关系、无法建立静态所有权的情况下使用?
答案是:如果对象之间的所有权不明确,weak_ptr
无法提供帮助。如果有一个循环,程序员必须找到它并打破它。另一种补救方法是使用具有完整垃圾收集的编程语言(例如:Java、C#、Go、Haskell),或使用与 C/C++ 一起使用的保守(=不完美)垃圾收集器(例如:Boehm GC) .
关于c++ - shared_ptr 和 weak_ptr 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4984381/