如何使用weak_ptr中断shared_ptr循环引用

时间:2014-11-23 05:02:24

标签: c++ smart-pointers c++03

我已经读过,weak_pointers可以用来打破循环引用。

考虑下面的循环引用示例

struct A
{
boost::shared_ptr<A> shrd_ptr;
};


boost::shared_ptr<A> ptr_A(boost::make_shared<A>());
boost::shared_ptr<A> ptr_b(boost::make_shared<A>());
ptr_A->shrd_ptr = ptr_b;
ptr_b->shrd_ptr = ptr_A;

现在上面是一个循环引用的例子,我想知道如何打破 上面的循环引用是使用weak_ptr

更新: 根据收到的建议,我想出了以下内容:

struct A
{
  boost::weak_ptr<A> wk_ptr;
};

    boost::shared_ptr<A> ptr_A (boost::make_shared<A>());
    boost::shared_ptr<A> ptr_B (boost::make_shared<A>());
    ptr_A->wk_ptr = ptr_B;
    ptr_B->wk_ptr = ptr_A;

这是正确的方法吗?

1 个答案:

答案 0 :(得分:34)

循环引用的经典示例是您有两个类AB,其中A引用了B,其中引用了A }:

#include <memory>
#include <iostream>

struct B;
struct A {
  std::shared_ptr<B> b;  
  ~A() { std::cout << "~A()\n"; }
};

struct B {
  std::shared_ptr<A> a;
  ~B() { std::cout << "~B()\n"; }  
};

void useAnB() {
  auto a = std::make_shared<A>();
  auto b = std::make_shared<B>();
  a->b = b;
  b->a = a;
}

int main() {
   useAnB();
   std::cout << "Finished using A and B\n";
}

如果两个引用均为shared_ptr,则表示A拥有BB拥有A,这应该会响起警钟。换句话说,AB保持活跃,BA保持活跃。

在此示例中,实例ab仅用于useAnB()函数,因此我们希望它们在函数结束时被销毁,但正如我们在运行时所看到的那样该程序不会调用析构函数。

解决方案是决定谁拥有谁。假设A拥有BB不拥有A,那么我们将A中的B引用替换为weak_ptr像这样:

struct B {
  std::weak_ptr<A> a;
  ~B() { std::cout << "~B()\n"; }  
};

然后,如果我们运行该程序,我们会发现ab已按预期销毁。

Live demo

编辑:在您的情况下,您建议的方法看起来完全有效。取消A的所有权以及其他拥有A的内容。