[C++ Notes] C++ Smart Pointers

Read this article

1. Smart pointer design ideas

2. Smart pointer is easy to use

3. Why is it not recommended to use auto_ptr

4. How to choose which smart pointer to use

Smart pointer design ideas

In the previous article on common pits when using C/C++ pointers, I summarized the various pits that may be encountered when using pointers in C/C++. The most common one is memory leaks. Remember the following example.
[C++ Notes] C++ Smart Pointers
[C++ Notes] C++ Smart Pointers

In this example, because an exception is thrown, the delete statement has no chance to execute, causing a memory leak. Of course, for this tens of lines of program, you can add a delete t to the catch statement to avoid it.

But what if it is an engineering project with dozens of W lines? I think you will fall apart! So is there a better way? The answer is yes.

We know that for ordinary local variables (non-static local variables), when they leave its scope, the operating system will automatically release them; and we also know that the class object is automatically called when the class is released. Destructor.

So we thought: If Test *t is not an ordinary pointer variable, but a class object, and the step of releasing dynamic memory is implemented in the destructor of the class; then as long as the pointer variable exits the scope The destructor will be called to achieve the purpose of releasing dynamic memory. This is the idea of ​​smart pointers.

According to the previous assumption, it is not difficult to implement a simple smart pointer, as follows:

class SmartPointer 
{
    private:
        Test* ptr;
    public:
        SmartPointer(Test* p) 
        {
         ptr = p;
        }
         ~SmartPointer() //析构函数释放资源
         {
         delete p;
         }
};

So how to use it, just need to change a little bit on the basis of the original code, as follows:

[C++ Notes] C++ Smart Pointers

C++ smart pointer is easy to use

Of course, the smart pointer that we implemented by ourselves is just to illustrate the idea of ​​smart pointer design, which is very crude. In normal use, there is no need to define smart pointers by yourself. C++ has already provided us with ready-made smart pointers to use.

C++ STL provides us with four types of smart pointers: auto_ptr, unique_ptr, shared_ptr and weak_ptr; among them, auto_ptr is provided by C++98, and it is recommended to abandon it in C++11. As for the reason, I will talk about it later; and unique_ptr, shared_ptr And weak_ptr was added to STL with the arrival of C++11.

The use of smart pointers is actually not difficult, as shown below:
[C++ Notes] C++ Smart Pointers
[C++ Notes] C++ Smart Pointers

Why is it not recommended to use auto_ptr

First look at the following statement:

auto_ptr<int> px(new int(8));
auto_ptr<int> py;
py = px;

What will the above assignment statement accomplish? If px and py are ordinary pointers, the two pointers will point to the same dynamically allocated int object. This is unacceptable because the program may try to delete the same object twice-once when px expires, and the other when py expires. We know that the same memory cannot be deleted twice. To avoid this problem, there are mainly the following two methods:

  • Establish the concept of ownership (ownership). For a particular object, only one smart pointer can be owned at the same time. For example, when smart pointer A points to object x, when B=A is executed, the original pointer A loses ownership of x, so that only the object is owned The constructor of the smart pointer will delete the object, unique_ptr and auto_ptr use this strategy.

  • Create smarter pointers and keep track of the number of smart pointers referencing specific objects. This is called reference counting. For example, when assigning a value, the count will increase by 1, and when the pointer expires, the count will decrease by 1. When it is reduced to 0, delete is called. This is the strategy adopted by shared_ptr.

Of course, the same strategy should be used for copy constructors.

Let's take a look at why it is recommended to abandon auto_ptr in C++11. Look at the following example.
[C++ Notes] C++ Smart Pointers
[C++ Notes] C++ Smart Pointers
From the running results of the program, when the assignment statement py = px is executed, the program crashes when it visits px. The reason is that the assignment statement py = px transfers the ownership of the object from px to py, and px has become a null pointer. Of course, it will be an error to access px again.

So what happens if you use unique_ptr or shared_ptr? Let’s test it. Let’s take a look at the unique_ptr situation first:
[C++ Notes] C++ Smart Pointers
[C++ Notes] C++ Smart Pointers
see if you use unique_ptr, you will get an error when compiling in this case. That is to say, even though unique_ptr also uses the ownership model like auto_ptr, the program will not wait when using unique_ptr. Crash during runtime, exposing potential errors to you during compilation

Ok, let’s take a look at the shared_ptr situation:
[C++ Notes] C++ Smart Pointers
[C++ Notes] C++ Smart Pointers
it runs normally when shared_ptr is used, because shared_ptr uses reference counting. After the assignment statement py = px is executed, px and py point to the same memory, but when you release the space, you need to judge in advance The size of the reference count value therefore does not cause the error of deleting an object multiple times.

How to choose which smart pointer

After understanding these types of smart pointers, you may naturally think of a question: Which smart pointer should be used in actual project applications? According to the characteristics of these smart pointers, the following suggestions are given:

  • If you want to use multiple pointers to the same object in the program, you should use shared_ptr; for example, there is an STL container that contains pointers, and now an STL algorithm that supports copy and assignment operations is used to manipulate the pointer elements of the container, then You should use shared_ptr. You cannot use unique_ptr (compiler error) and auto_ptr (uncertain behavior).

  • If the program does not need to use multiple pointers to the same object, you can use unique_ptr; if the function uses new to allocate memory and returns a pointer to the memory, it is a good choice to declare its return type as unique_ptr. In this way, the ownership is transferred to the unique_ptr that accepts the return value, and the smart pointer will be responsible for calling delete.

  • When the conditions required by unique_ptr are met, auto_ptr can also be used, but unique_ptr is a better choice.

to sum up

This article only summarizes the basic usage of smart pointers in general, and there are many points worth noting in actual use. Later articles will continue to summarize these details. In short, the process of learning C++ is a process of stepping on the pit.

Recommended reading:

[Welfare] Video sharing of online boutique courses collected by myself (
Part 1 ) [Protocol Forest] Postman and Post Office (Overview of Network Protocol)
[Data Structure and Algorithm] Easy-to-understand explanation of bit ordering
[C++ Notes] C++11 concurrent programming (1) ) Start the thread journey
[C++ Notes] Common pitfalls in using C/C++ pointers
[C++ Notes] Detailed explanation of static and dynamic libraries (on)

Coding

The code farmer has the right way to provide you with easy-to-understand technical articles to make technology easier!
[C++ Notes] C++ Smart Pointers

Focus on server background technology stack knowledge summary sharing

Welcome to pay attention to communication and common progress

Guess you like

Origin blog.51cto.com/15006953/2552128