c++ - shared_ptr 和 weak_ptr 的区别

标签 c++ c++11 shared-ptr weak-ptr cyclic-reference

我正在阅读 Scott Meyers “Effective C++”一书。有人提到有 tr1::shared_ptrtr1::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/

相关文章:

c++ - 可 move 元素的 vector 会有效地调整大小吗?

c++ - 从 boost::shared_ptr 到 std::shared_ptr 的转换?

c++ - 用 std::shared_ptr 替换 vector 中的原始指针

c++ - 如何使用 C++ 在 OSX 中获取当前用户的语言环境

c++ - C++11 中的线程 : A better way to approach lock guards?

c++11:使用中央命令映射器调用虚拟基类方法

C++11 空标志类

c++ - 如何使用 shared_ptr 在类型删除类中显示基础数据

c++ - 使用这个 "shortcutting function"是一个好习惯吗?

c++ - 以编程方式生成声音