This article mainly introduces boost The use of intelligent pointer in .

    Memory management is a complicated problem ,C++ There are two implementations in : Garbage collection mechanism and intelligent pointer . The garbage collection mechanism is not affected by performance and other reasons C++ They are highly praised by the big men ,
And smart pointers are considered to be the solution C++ The optimal scheme of memory problem .

1. definition

     A smart pointer is a C++ Object of , The object behaves like a pointer , But it can be automatically deleted when it is not needed . Pay attention to this “ When it's not needed ”,
This is not a precise definition . This can refer to many aspects when it is not needed : Local variable exit function scope , Class is destructed ……. therefore boost Different intelligent pointers are defined to manage different scenarios .

shared_ptr<T> An internal reference counter is maintained to determine whether the pointer needs to be released . yes boost The most commonly used smart pointer in .
scoped_ptr<t> When the scope of this pointer disappears, it is released automatically
intrusive_ptr<T> A reference counter is also maintained , than shared_ptr Better performance . But the requirements T Provide this counter yourself .
weak_ptr<T> Weak pointer , To make peace with shared_ptr Combined use
shared_array<T> and shared_ptr be similar , But the access is an array
scoped_array<T> and scoped_ptr be similar , But the access is an array
2. Boost::scoped_ptr<T>

    scoped_ptr yes boost The simplest intelligent pointer in .scoped_ptr It's also very simple ,
When a pointer leaves its scope , Release related resources . Special attention must be paid to scoped_ptr
Ownership of pointers cannot be shared or transferred . In other words, this memory address can only be used for the declared variables , It can't be used for other purposes .

    Here is scoped_ptr Several characteristics of :

* scoped_ptr The efficiency and space consumption of the built-in pointer is almost the same .
* scoped_ptr Cannot be used on containers in standard libraries .( use shared_ptr replace )
* scoped_ptr Cannot point to an area of memory that can grow dynamically ( use scoped_array replace )

<> 1 class test
2 {
3 public:
4 void print()
5 {
6 cout << "test print now" <<endl;
7 }
8 };
9 int _tmain(int argc, _TCHAR* argv[])
10 {
11 boost::scoped_ptr<test> x(new test);
12 x->print();
13 return 0;
14 } <>


    shared_ptr It has the following characteristics :

* Maintain a reference counter internally , When a pointer points to this memory area, it is a reference count +1, conversely -1, If there is no pointer to this area , The reference counter is 0, Free memory area .
* Ownership can be shared and transferred .
* Can be used by containers in the standard library
* Cannot point to a dynamically growing block of memory ( use share_array replace )
We can take a look at the following examples :

<> 1 int _tmain(int argc, _TCHAR* argv[])
2 {
3 boost::shared_ptr<test> ptr_1(new test);
4 ptr_1->print();// The reference count is 1
5 boost::shared_ptr<test> ptr_2 = ptr_1;
6 ptr_2->print();// The reference count is 2
7 ptr_1->print();// Reference count is still 2
8 return 0;
9 } <>

4. Boost::intrusive_ptr<T>

    intrusive_ptr Main and share_ptr equally , contrast share_ptr, It's more efficient , But you need to maintain a reference counter yourself .

shared_ptr It provides more perfect function than ordinary pointer . There is a small price , A shared pointer takes up more space than a normal pointer , Each object has a shared pointer , This pointer has a reference counter for easy release . But for most of the reality , These are negligible .intrusive_ptr
Provides a compromise solution . It provides a lightweight reference counter , But the object itself must already have an object reference counter . It's not a bad idea , When you design your own classes, implement the same work as smart pointers , Then a reference counter must have been defined , This requires less memory , And it can improve execution performance . If you want to use intrusive_ptr
Pointing type T, Then you need to define two functions :intrusive_ptr_add_ref
and intrusive_ptr_release. Here is a simple example of how to implement it in your own class :

#include "boost/intrusive_ptr.hpp" // forward declarations class CRefCounted;
namespace boost { void intrusive_ptr_add_ref(CRefCounted * p); void
intrusive_ptr_release(CRefCounted * p); }; // My Class class CRefCounted {
private: long references; friend void
::boost::intrusive_ptr_add_ref(CRefCounted * p); friend void
::boost::intrusive_ptr_release(CRefCounted * p); public: CRefCounted() :
references(0) {} // initialize references to 0 }; // class specific
addref/release implementation // the two function overloads must be in the
boost namespace on most compilers: namespace boost { inline void
intrusive_ptr_add_ref(CRefCounted * p) { // increment reference count of object
*p ++(p->references); } inline void intrusive_ptr_release(CRefCounted * p) { //
decrement reference count, and delete object when reference count reaches 0 if
(--(p->references) == 0) delete p; } } // namespace boost

  This is the simplest ( Non thread safe ) Implement the operation . But as a general operation , It might be useful to provide a base class to do this , Maybe it will be introduced in other places .        

5. Boost::weak_ptr<T>


Comparison of strong reference and weak reference :

A strong reference when the referenced object is alive , This reference also exists ( That is to say , When there is at least one strong reference , Then the object cannot be released ).boost::share_ptr It's a strong reference . Relatively speaking , Weak references do not necessarily exist when the referenced object is alive . It's just a reference when it exists .

Is a smart pointer to execute a weak reference . When you need it, you can use a strong ( share ) The pointer points to it ( When the object is released , It is empty ), Of course, this strong pointer should be released immediately after use , In the example above, we can change it to a weak pointer .

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 } };
    weak_ptr It's a weak pointer .weak_ptr cover shared_ptr control ,
It can pass through share_ptr Or lock Member functions are converted to share_ptr.

    weak_ptr One of the biggest features of is that it shares a share_ptr Memory for , But whether it is a structure or a structure weak_ptr Does not affect the reference counter .

<> 1 int _tmain(int argc, _TCHAR* argv[])
2 {
3 boost::shared_ptr<test> sharePtr(new test);;
4 boost::weak_ptr<test> weakPtr(sharePtr);
5 //weakPtr Is used to save the pointer to this memory area
6 // A lot of other things
7 boost::shared_ptr<test> sharePtr_2 = weakPtr.lock();
8 if (sharePtr_2)
9 sharePtr_2->print();
10 return 0;
11 } <>

6. Boost::shared_array<T> and Boost::scoped_array<T>

    As mentioned earlier shared_ptr and scoped_ptr Memory cannot be used for arrays (new
[]), therefore shared_array and scoped_array It's their substitute . We can take a look shared_array Usage of

<> 1 int _tmain(int argc, _TCHAR* argv[])
2 {
3 const int size = 10;
4 boost::shared_array<test> a(new test[]);
5 for (int i = 0; i < size; ++i)
6 a[i].print();
7 return 0;
8 } <>

7. Several points for attention in using intelligent pointer

    Here are a few points to pay attention to when using smart pointers :

* When declaring a smart pointer, instantiate it immediately , And it must not be released manually .
* …_ptr<T> no T* type . therefore :
                a: When you make a statement …_ptr<T> instead of ….._ptr<T*>

                b: Can't put T* The pointer of type is assigned to it

                c: Can't write ptr=NULl, And use ptr.reset() replace .

* You can't recycle references .
* Don't declare temporary share_ptr, Then pass the pointer to a function
8. summary

    Smart pointer is relatively simple to use , And it can be solved more effectively C++ Memory leaks , Use it C++ Let's use our children's shoes .

©2019-2020 Toolsou All rights reserved,
Final review of database : Summary of comprehensive application questions use Python Make simple games Laplance operator ( Second derivative ) Convert hard disk to GPT Partition format Python Implementation of Hanoi Tower code about String How to create objects vue3 Learning journey 1—— establish vue3 project java String from back to front _Java String String summary use Python Write a story about plants versus zombies 【 Greedy Algorithm 】 Huffman coding problem