weak_ptr resolves memory leaks caused by shared_ptr ring references

Source: Internet
Author: User

Circular reference:

Reference counting is a convenient memory management mechanism, but it has a great disadvantage, that is, the object that cannot manage circular references. A simple example is as follows:

#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

Class parent;
class children;

typedef boost::shared_ptr<parent> PARENT_PTR;
typedef boost::shared_ptr<children> CHILDREN_PTR;

Class Parent
{
Public
~parent () {std::cout << "destroying parent\n";}

Public
Children_ptr children;
};

Class children
{
Public
~children () {std::cout << "destroying children\n";}

Public
Parent_ptr parent;
};


void Test ()
{
Parent_ptr father (new parent ());
Children_ptr Son (new children);

Father->children = Son;
Son->parent = Father;
}

void Main ()
{
std::cout<< "Begin test...\n";
Test ();
std::cout<< "End test.\n";
}

Run the program to see that even after the test function is exited, since the parent and children objects refer to each other, their reference count is 1 and cannot be automatically freed, and the two objects are no longer accessible. This leads to the infamous memory leak in C + +.

Generally, there are three possible ways to remove this circular reference: when only the last reference is left, you need to manually break the circular reference to release the object. When parent's lifetime exceeds the lifetime of children, children instead uses a normal pointer to point to parent. Use smart pointers with weak references to break this circular reference.

Although these three methods are feasible, both Method 1 and Method 2 require manual control by the programmer, which is cumbersome and error-prone. Here is a brief introduction to the third method and the weak reference smart pointer boost::weak_ptr in boost.

Strong references and weak references

A strong reference if the referenced object is alive, the reference also exists (that is, when at least one strong reference is present, the object cannot be released). Boost::share_ptr is a strong reference.

Weak references do not necessarily exist when the referenced object is alive. It's just a reference when it's there. A weak reference does not modify the reference count of the object, which means that the weak reference does not manage the object's memory and is functionally similar to a normal pointer, whereas a weak reference can detect whether the managed object has been freed, thereby avoiding access to illegal memory.

Boost::weak_ptr

Boost::weak_ptr<t> is a weak-referenced smart pointer provided by boost, and its declaration can be simplified as follows:

Namespace Boost {

Template<typename T>class weak_ptr {
Public
Template <typename y>
weak_ptr (const shared_ptr<y>& R);

weak_ptr (const weak_ptr& R);

~weak_ptr ();

t* get () const;
BOOL expired () const;
Shared_ptr<t> lock () const;
};
}

As you can see, boost::weak_ptr must be converted from a boost::share_ptr or another boost::weak_ptr, which means that the memory management of the object is the boost::share_ptr of that strong reference. Boost::weak_ptr only provides a means of access to management objects.

Boost::weak_ptr In addition to the basic access functionality of the managed objects (through the Get () function), there are two common functional functions: expired () is used to detect whether the managed object has been released, and lock () is used to get the strong reference pointer to the managed object.

To break the circular reference by boost::weak_ptr

Because a weak reference does not change the reference count, like a normal pointer, you can disassociate a circular reference by using a weak reference to the side of the circular reference. For the example above, you can disassociate the circular reference by changing the definition of children to the following:

Class children
{
Public
~children () {std::cout << "destroying children\n";}

Public
Boost::weak_ptr<parent> parent;
};

Finally, it is worth mentioning that although the circular reference can be effectively lifted by a weak reference pointer, however, this method must be used when the programmer can foresee a circular reference, or this is just a compile-time solution, or it can cause a memory leak if a circular reference occurs during the process. Therefore, do not think that as long as the use of smart pointers can eliminate memory leaks. After all, for C + +, because there is no garbage collection mechanism, the memory leak for every programmer is a very headache problem.

VS2008 Sample code: [cpp]  View Plain copy #include   "stdafx.h"    #include  <string>    #include  <iostream>      #include   "Memory"    #define  _ crtdbg_map_alloc      #include  <stdlib.h>      #include   <crtdbg.h>      #define &NBSP;NEW&NBSP;NEW ( _client_block, __file__, __ line__)       #define  _LOOP_POINTER_         class  parent;   class children;      #ifdef  _LOOP_POINTER_   typedef  std::tr1::shared_ptr<parent> parent_ptr;   #else    typedef std::tr1:: weak_ptr<parent> parent_ptr;   #endif       typedef std::tr1::shared _ptr<children> children_ptr;      class parent   {   public:       ~parent ()  { std::cout << "destroying  parent\n "; }      public:       children_ptr children ;  };      class children   {   public:        ~children ()  { std::cout << "destroying children\n"; }       public:       parent_ptr parent;  };         void test ()    {       children_ptr son (New children);   #ifdef  _LOOP_POINTER_       parent_ptr  Father (New parent ());   #else        std::tr1::shared_ptr<parent > father (New parent ());           son->pArent = parent_ptr (father);   #endif           father- >children = son;         }                Int _tmain (int argc, _tchar* argv[])    {        _crtsetdbgflag (_CRTDBG_ALLOC_MEM_DF&NBSP;|&NBSP;_CRTDBG_LEAK_CHECK_DF);               std::cout<< "begin test...\n";        test ();       std::cout<< "End test . \ n ";          return 0;  }  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.