Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
293 views
in Technique[技术] by (71.8m points)

c++ - How to break shared_ptr cyclic reference using weak_ptr

I have read that weak_pointers can be used to break cyclic references.

Consider the following example of a cyclic reference

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;

Now above is a case of cyclic reference and I wanted to know how I can break the cyclic reference above by using weak_ptr ?

Update : Based on suggestion received I came up with the following :

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;

Will this be the correct approach ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The classic example of cyclic references is where you have two classes A and B where A has a reference to B which has a reference to A:

#include <memory>
#include <iostream>

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

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

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

If both references are shared_ptr then that says A has ownership of B and B has ownership of A, which should ring alarm bells. In other words, A keeps B alive and B keeps A alive.

In this example the instances a and b are only used in the useAnB() function so we would like them to be destroyed when the function ends but as we can see when we run the program the destructors are not called.

The solution is to decide who owns who. Lets say A owns B but B does not own A then we replace the reference to A in B with a weak_ptr like so:

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

Then if we run the program we see that a and b are destroyed as we expect.

Live demo

Edit: In your case, the approach you suggested looks perfectly valid. Take ownership away from A and something else owns the As.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...