C + + Smart Pointer instance detailed _c language

Source: Internet
Author: User

In this paper, the concept and usage of the intelligent pointer in C + + are explained in detail, which helps readers to deepen their understanding of the intelligent pointer. Details are as follows:

First, Introduction

Because the C + + language does not have an automatic memory recovery mechanism, the programmer will manually delete each new memory. The programmer forgets to delete, the process is too complex, resulting in no delete, and the exception causes the program to quit prematurely, and it is not uncommon to not execute the delete.
Using smart pointers can effectively alleviate such problems, this article mainly explains the use of smart pointers. Include: Std::auto_ptr, Boost::scoped_ptr, Boost::shared_ptr, Boost::scoped_array, Boost::shared_array, Boost::weak_ptr, Boost:: Intrusive_ptr. You might think, is it really necessary to have so many smart pointers to solve new and delete matching problems? After reading this article, I think your heart will naturally have the answer.

Here are the 7 smart pointers (SMART_PTR) that are explained in order.

second, the specific use

1. Overall

For the compiler, the smart pointer is actually a stack object, not a pointer type, and the smart pointer releases its managed heap memory through the destructor at the end of the stack object lifetime . all Smart pointers overload the "operator->" operator, returning directly to the object's reference to manipulate the object. Accessing the smart pointer The original method uses the "." Operator.

access to the bare pointers contained by the smart pointer can be used with the Get () function . Because the smart pointer is an object, the if (My_smart_object) is always true, and to determine whether the naked pointer of the smart pointer is empty, you need to judge this: if (My_smart_object.get ()).

The smart pointer contains the reset () method, and if you do not pass the parameter (or pass NULL), the smart pointer frees the currently managed memory. If you pass an object, the smart pointer releases the current object to manage the new incoming object.
We write a test class to assist in parsing:

Class Simple {public
 : simple
 (int param = 0) {Number
  = param;
  Std::cout << "simple:" << number << Std::endl; 
 }
 ~simple () {
  std::cout << "~simple:" << number << Std::endl;
 }
 void Printsomething () {
  std::cout << "printsomething:" << info_extend.c_str () << Std::endl;
 }
 std::string info_extend;
 int number;
};

2, Std::auto_ptr

Std::auto_ptr belong to STL, of course namespace STD, include header file #include <memory> can use. Std::auto_ptr can easily manage a single heap of memory objects.

We start with the code analysis:

void Testautoptr () {
std::auto_ptr<simple> my_memory (New Simple (1));  Create object, Output: Simple:1
if (My_memory.get ()) {              //judge whether the smart pointer is empty
my_memory->printsomething ();          Use Operator-> to invoke functions in a smart pointer object
my_memory.get ()->info_extend = "addition";   Returns the bare pointer using get () and assigns the inner object
my_memory->printsomething ();          Print again, indicating that the above assignment was successful
(*my_memory). Info_extend + = "other";      Use operator* to return the inner object of the smart pointer, and then use the "." Invokes a function in a smart pointer object
my_memory->printsomething ();          Print again, indicating that the above assignment
 was successful}                       //my_memory Stack object is about to end lifetimes, the destructor heap object simple (1)

The results of the execution are:

Simple:1
printsomething:
printsomething:addition
printsomething:addition other
~simple:1

All of the above for the normal use of std::auto_ptr code, everything seems to be good, anyway we do not have to show the use of the damn Delete.

In fact, we look at another example as follows:

void TestAutoPtr2 () {
 std::auto_ptr<simple> my_memory (New Simple (1));
 if (My_memory.get ()) {
  std::auto_ptr<simple> my_memory2;  Create a new My_memory2 object
  my_memory2 = my_memory;       Copy the old my_memory to My_memory2
  my_memory2->printsomething ();    Output information, replication success
  my_memory->printsomething ();    Crash
 }
}

Finally, as the code led to a crash, such as on the code in absolute accordance with C + + programming ideas, actually collapsed, follow the std::auto_ptr source, we see, the culprit is "My_memory2 = my_memory", this line of code, My_memory2 completely captured my _memory memory management ownership, resulting in my_memory dangling, resulting in a crash when used last.

Therefore, when using std::auto_ptr, you must never use the "operator=" operator. As a library, do not allow users to use, do not explicitly reject, how many will feel a bit unexpected.

After watching Std::auto_ptr's first example, let's look at one more:

void TestAutoPtr3 () {
 std::auto_ptr<simple> my_memory (New Simple (1));
 
 if (My_memory.get ()) {
  my_memory.release ();
 }
}

The results of the execution are:

Simple:1

Do you see anything out of the ordinary? The object we created was not destructor, no output "~simple:1", causing memory leaks. When we don't want my_memory to survive, we call the release () function to free up memory, which results in memory leaks (in a memory-constrained system, if my_memory takes up too much memory, we consider returning it immediately after use, rather than waiting until My_memory Returned only after the end of the life cycle.

The correct code should be:

void TestAutoPtr3 () {
 std::auto_ptr<simple> my_memory (New Simple (1));
 if (My_memory.get ()) {
  simple* temp_memory = My_memory.release ();
  Delete temp_memory;
 }


Or

void TestAutoPtr3 () {
 std::auto_ptr<simple> my_memory (New Simple (1));
 if (My_memory.get ()) {
  my_memory.reset ();//release my_memory internal managed Memory
 }
}

The original std::auto_ptr release () function simply yields memory ownership, which clearly does not conform to C + + programming ideas.
Summary: Std::auto_ptr can be used to manage the memory of individual objects, but please note the following points:

(1) Try not to use "operator=". If used, do not use the previous object again.
(2) Remember that the release () function does not free objects, only returns ownership.
(3) Std::auto_ptr is best not to pass as a parameter (the reader can write the code to determine why not).
(4) Because of the "operator=" Problem of std::auto_ptr, the object of its management cannot be put into std::vector and other containers.
There are a lot of restrictions on the use of a std::auto_ptr, can not be used to manage the heap memory array, this should be your current thinking of things, I also think that a lot of restrictions, which day a careless, it caused the problem.
Because STD::AUTO_PTR caused a lot of problems, some of the design is not very consistent with C + + programming ideas, so triggered the following boost smart pointers, boost smart pointers can solve the problem.
Let's keep looking down.

3, Boost::scoped_ptr

Boost::scoped_ptr belongs to boost library, defined in namespace boost, contains header files #include <boost/smart_ptr.hpp> can be used. Boost::scoped_ptr, like Std::auto_ptr, can easily manage a single heap of memory objects, in particular, boost::scoped_ptr exclusive ownership, to avoid std::auto_ptr annoying a few problems.
Let's start by analyzing the code:

void Testscopedptr () {
 boost::scoped_ptr<simple> my_memory (New Simple (1));
 if (My_memory.get ()) {
  my_memory->printsomething ();
  My_memory.get ()->info_extend = "addition";
  My_memory->printsomething ();
  (*my_memory). Info_extend = "other";
  My_memory->printsomething ();
  
  My_memory.release ();      Compiler error:scoped_ptr has no release function
  std::auto_ptr<simple> my_memory2;
  My_memory2 = my_memory;    Compilation Error:scoped_ptr does not overload operator=, does not cause ownership transfer
 }
}

First, we can see that boost::scoped_ptr can also be used as normal as auto_ptr. However, it does not have the release () function and does not cause a previous memory leak problem. Second, because BOOST::SCOPED_PTR is exclusive ownership, so explicitly reject the user to write "My_memory2 = my_memory" Statements such as, can alleviate std::auto_ptr a few annoying problems.
Because Boost::scoped_ptr exclusive ownership, when we really need to copy the smart pointer, the requirements will not be met, so we introduce a smart pointer, specifically for processing replication, parameter transfer, which is the following boost::shared_ptr.

4, Boost::shared_ptr

The

Boost::shared_ptr belongs to the Boost library, defined in namespace boost, and contains header files #include <boost/smart_ptr.hpp> can be used. Above we see BOOST::SCOPED_PTR exclusive ownership, not allowed to assign, copy, Boost::shared_ptr is dedicated to share ownership, because to share ownership, it uses the reference count internally. Boost::shared_ptr is also used to manage a single heap of memory objects.
Let's start parsing from code:

void Testsharedptr (boost::shared_ptr<simple> memory) {//NOTE: No need to use reference (or const reference)
 memory-> Printsomething ();
 Std::cout << "testsharedptr usecount:" << memory.use_count () << Std::endl;
}
 
void TestSharedPtr2 () {
 boost::shared_ptr<simple> my_memory (New Simple (1));
 if (My_memory.get ()) {
  my_memory->printsomething ();
  My_memory.get ()->info_extend = "addition";
  My_memory->printsomething ();
  (*my_memory). Info_extend = "other";
  My_memory->printsomething ();
 }
 
 Std::cout << "TestSharedPtr2 usecount:" << my_memory.use_count () << Std::endl;
 Testsharedptr (my_memory);
 Std::cout << "TestSharedPtr2 usecount:" << my_memory.use_count () << Std::endl;
 
 My_memory.release ()//Compile error: Similarly, shared_ptr has no release function
}

The results of the execution are:

Simple:1
printsomething:
printsomething:addition
printsomething:addition other
TestSharedPtr2 Usecount:1
printsomething:addition Other
testsharedptr usecount:2
TestSharedPtr2 usecount:1
~ Simple:1

Boost::shared_ptr can also be very convenient to use. And there is no release () function. Crucially, Boost::shared_ptr internally maintains a reference count, which enables replication, parameter passing, and so on. Boost::shared_ptr provides a function Use_count (), which returns the reference count within the boost::shared_ptr. Looking at the execution results, we can see that in the TESTSHAREDPTR2 function, the reference count is 1, after passing the argument (a copy is made here), within the function testsharedptr, the reference count is 2, and the reference count is reduced to 1 after Testsharedptr returns. When we need to use a shared object, Boost::shared_ptr is the best.
Here, we've seen the smart pointer management of a single object, about smart pointer management arrays, which we'll talk about next.

5, Boost::scoped_array

Boost::scoped_array belongs to boost library, defined in namespace boost, contains header files #include <boost/smart_ptr.hpp> can be used.
Boost::scoped_array is used to manage dynamic arrays. Like Boost::scoped_ptr, it is exclusive ownership.

Let's start by analyzing the code:

void Testscopedarray () {
   boost::scoped_array<simple> my_memory (new simple[2);////Use an array of memory to initialize
   if (my_ Memory.get ()) {
    my_memory[0]. Printsomething ();
    My_memory.get () [0].info_extend = "addition";
    My_memory[0]. Printsomething ();
    (*my_memory) [0].info_extend + = "other";      Compiled Error,scoped_ptr no overloaded operator*
    my_memory[0].release ();               Ditto, no release function
    boost::scoped_array<simple> my_memory2;
    My_memory2 = my_memory;               Compile error, IBID., no overloaded operator=
   }
  }

Boost::scoped_array is similar to boost::scoped_ptr, does not support replication, and needs to be initialized with a dynamic array. In addition, Boost::scoped_array does not overload the "operator*", in fact, this is not a big deal, in general, we use the Get () function more specifically.

The following must speak Boost::shared_array, a smart pointer class that solves replication and parameter passing with reference counting.

6, Boost::shared_array
Boost::shared_array belongs to boost library, defined in namespace boost, contains header files #include <boost/smart_ptr.hpp> can be used.

Because Boost::scoped_array exclusive ownership, obviously in many cases (parameter passing, object assignment, etc.) does not meet the demand, so we introduce Boost::shared_array. As with boost::shared_ptr, reference counts are used internally.

Let's start by analyzing the code:

void Testsharedarray (boost::shared_array<simple> memory) {//NOTE: No need to use reference (or const reference)
 Std::cout << "Testsharedarray usecount:" << memory.use_count () << Std::endl;
}
 
void TestSharedArray2 () {
 boost::shared_array<simple> my_memory (new simple[2));
 if (My_memory.get ()) {
  my_memory[0]. Printsomething ();
  My_memory.get () [0].info_extend = "addition";
  My_memory[0]. Printsomething ();
  MY_MEMORY[1]. Printsomething ();
  My_memory.get () [1].info_extend = "addition One";
  MY_MEMORY[1]. Printsomething ();
  (*my_memory) [0].info_extend + = "other"; Compilation Error,scoped_ptr no overloaded operator*
 }
 std::cout << "TestSharedArray2 usecount:" << my_ Memory.use_count () << Std::endl;
 Testsharedarray (my_memory);
 Std::cout << "TestSharedArray2 usecount:" << my_memory.use_count () << Std::endl;
}

The results of the execution are:

simple:0
simple:0
printsomething:
printsomething:addition
printsomething:
printsomething : addition
TestSharedArray2 usecount:1 testsharedarray usecount:2 TestSharedArray2 usecount:1
~ simple:0
~simple:0

As with boost::shared_ptr, reference counts are used, which can be copied and passed by parameters.

So far, the smart pointers we've talked about are std::auto_ptr, Boost::scoped_ptr, Boost::shared_ptr, Boost::scoped_array, Boost::shared_array. These smart pointers are basically enough for us to use, with 90% of the code using a standard smart pointer on these 5 kinds. There are two kinds of smart pointers that are sure to be useful, but what's the use?

7, Boost::weak_ptr

Boost::weak_ptr belongs to boost library, defined in namespace boost, contains header files #include <boost/smart_ptr.hpp> can be used.
Before we talk about Boost::weak_ptr, let's take a look at what we explained earlier. It seems that boost::scoped_ptr, boost::shared_ptr these two smart pointers can solve all the single object memory management, there is also a boost::weak_ptr, whether there are some circumstances we do not take into account?
Answer: Yes. First of all, boost::weak_ptr is specially prepared for boost::shared_ptr. Sometimes, we only care about the ability to use objects, not the internal reference count. BOOST::WEAK_PTR is the Boost::shared_ptr Observer (Observer) object, and the observer means that boost::weak_ptr only references the boost::shared_ptr without changing its reference count, when the observed After the boost::shared_ptr is invalidated, the corresponding boost::weak_ptr is also invalidated.
Let's start by analyzing the code:

  void Testweakptr () {
   boost::weak_ptr<simple> my_memory_weak;
   Boost::shared_ptr<simple> My_memory (New Simple (1));
 
   Std::cout << "Testweakptr boost::shared_ptr usecount:" << my_memory.use_count () << Std::endl;
   My_memory_weak = my_memory;
   Std::cout << "Testweakptr boost::shared_ptr usecount:" << my_memory.use_count () << Std::endl;
}

The results of the execution are:

Simple:1
testweakptr boost::shared_ptr usecount:1
testweakptr boost::shared_ptr usecount:1
~simple:1

We see that despite being assigned, the internal reference count does not change, of course, the reader can also try to pass parameters and other circumstances.
Now, the question is, what is the role of boost::weak_ptr? From the above example, it does not seem to have any effect, in fact, boost::weak_ptr is mainly used in software architecture design, can be in the base class (where the base class is not abstract base class, but is inherited from the abstract base class virtual base class) in the definition of a boost::weak_ptr, to point to the subclass of the Boost::shared_ptr, so that the base class simply observes that its boost::weak_ptr is empty, it knows that subclasses have not assigned to themselves, without affecting the reference count of subclasses boost::shared_ptr, to reduce complexity and better manage objects.

8, Boost::intrusive_ptr

Boost::intrusive_ptr belongs to boost library, defined in namespace boost, contains header files #include <boost/smart_ptr.hpp> can be used.
After talking about 6 kinds of smart pointers, for general programs, C + + heap memory management is enough, now there is a boost::intrusive_ptr, this is an inserted smart pointer, the internal does not contain reference count, the programmer to add the reference count themselves, Otherwise compile but (⊙﹏⊙ b Khan). Personally feel this smart pointer is not very useful, at least I did not use. Interested friends themselves to study the source code OH.


Third, summary

Having said so many smart pointers, it is necessary to summarize these smart pointers:

1, in the use of boost library occasions, refused to use std::auto_ptr, because it not only does not conform to C + + programming ideas, but also very easy to make mistakes.
2. Use Boost::scoped_ptr (of course the dynamic array uses Boost::scoped_array) when determining that the object does not need to be shared.
3, in the case that the object needs to be shared, use BOOST::SHARED_PTR (of course the dynamic array uses Boost::shared_array).
4, in need of access to boost::shared_ptr objects, and do not want to change their reference count, the use of boost::weak_ptr, commonly used in software framework design.
5, the last point, but also the most demanding point: in your code, do not appear the DELETE keyword (or the C language free function), because you can use the smart pointer to manage.

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.