strong reference and weak reference

Cyclic References

Reference counting is a convenient resource management mechanism, it has one fundamental drawback though: cyclic references are not freed automatically, and are hard to detect by the computer. The simplest example is this:

struct
 CDad;

struct
 CChild;



typedef
 boost::shared_ptr<
CDad>
   CDadPtr;

typedef
 boost::shared_ptr<
CChild>
 CChildPtr;





struct
 CDad : public
 CSample

{

   CChildPtr myBoy;

};



struct
 CChild : public
 CSample

{

  CDadPtr myDad;

};



//
 a "thing" that holds a smart pointer to another "thing":




CDadPtr   dad(new
 CDad); 

CChildPtr child(new
 CChild);



//
 deliberately create a circular reference:


dad->
myBoy = child; 

child->
myDad = dad;





//
 resetting one ptr...


child.reset();

dad still references the CDad object, which itself references the CChild. The whole thing looks like this:

If we now call dad.reset(), we lose all "contact" with the two objects. But this leaves both with exactly one reference, and the shared pointers see no reason to delete either of them! We have no access to them anymore, but they mutually keep themselves "alive". This is a memory leak at best; in the worst case, the objects hold even more critical resources that are not released correctly.

The problem is not solvable with a "better" shared pointer implementation (or at least, only with unacceptable overhead and restrictions). So you have to break that cycle. There are two ways:

  1. Manually break the cycle before you release your last reference to it
  2. When the lifetime of Dad is known to exceed the lifetime of Child, the child can use a normal (raw) pointer to Dad.
  3. Use a boost::weak_ptr to break the cycle.

Solutions (1) and (2) are no perfect solutions, but they work with smart pointer libraries that do not offer a weak_ptr like boost does. But let's look at weak_ptr in detail:

Using weak_ptr to break cycles

Strong vs. Weak References:

A strong reference keeps the referenced object alive (i.e., as long as there is at least one strong reference to the object, it is not deleted). boost::shared_ptr acts as a strong reference. In contrast, a weak reference does not keep the object alive, it merely references it as long as it lives.

Note that a raw C++ pointer in this sense is a weak reference. However, if you have just the pointer, you have no ability to detect whether the object still lives.

boost::weak_ptr<T> is a smart pointer acting as weak reference. When you need it, you can request a strong (shared) pointer from it. (This can be NULL if the object was already deleted.) Of course, the strong pointer should be released immediately after use. In the above sample, we can decide to make one pointer weak:

struct
 CBetterChild : public
 CSample

{

  weak_ptr<
CDad>
 myDad;



  void
 BringBeer()

  {

    shared_ptr<
CDad>
 strongDad = myDad.lock(); //
 request a strong pointer


    if
 (strongDad)                      //
 is the object still alive?


      strongDad->
SetBeer();

    //
 strongDad is released when it goes out of scope.


    //
 the object retains the weak pointer


  }

};

See the Sample 5 for more.

 

reference: http://www.codeproject.com/KB/stl/boostsmartptr.aspx#Cyclic%20References

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值