A C + + smart pointer

Source: Internet
Author: User

First, Introduction

Since the C + + language does not have an automatic memory recycling mechanism, the programmer will manually delete each new memory. The programmer forgets the delete, the process is too complex, resulting in no delete, the exception causes the program to exit prematurely, and the absence of a delete is not uncommon.

The use of smart pointers can effectively alleviate such problems, this article mainly explains the use of smart pointers. Including: Std::auto_ptr, Boost::scoped_ptr, Boost::shared_ptr, Boost::scoped_array, Boost::shared_array, Boost::weak_ptr, Boost:: Intrusive_ptr. You might think that so many smart pointers are really necessary to solve the new and delete matching problems? After reading this article, I think your heart will naturally have the answer.

Here are some of 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 at the end of the life of the stack object, the smart pointer releases the heap memory it manages through the destructor. All smart pointers overload the "operator->" operator, returning directly to the object's reference to manipulate the object. The original method of accessing the smart pointer uses the "." Operator.

The Access smart pointer contains a bare pointer that can be used with the Get () function. Because the smart pointer is an object, if (My_smart_object) is always true, to determine whether the smart pointer's bare pointer is empty, you need to judge this: if (My_smart_object.get ()).

The smart pointer contains the reset () method, and if the parameter is not passed (or NULL is passed), the smart pointer frees the currently managed memory. If an object is passed, the smart pointer frees the current object to manage the new incoming object.

We write a test class to assist the analysis:

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 belongs to STL, of course, in namespace STD, including header file #include <memory> can be used. 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 ()) {//To determine if the smart pointer is empty

My_memory->printsomething (); To invoke a function in a smart pointer object using operator->

My_memory.get ()->info_extend = "addition"; Returns a bare pointer using get () and assigns a value to the inner object

My_memory->printsomething (); Print again to indicate 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 "." Invoke a function in a smart pointer object

My_memory->printsomething (); Print again to indicate that the above assignment was successful

}

}//My_memory stack objects are nearing the end of their lifetimes, and the destructor objects are simple (1)

The result of the execution is:

Simple:1

Printsomething:

Printsomething:addition

Printsomething:addition Other

~simple:1

The above is the normal use of std::auto_ptr code, everything seems good, no matter how we show the use of the damned 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; To create a new My_memory2 object

My_memory2 = my_memory; Copy the old my_memory to My_memory2

My_memory2->printsomething (); Output information, replication succeeded

My_memory->printsomething (); Collapse

}

}

Finally, as the code leads to crashes, such as the code is absolutely consistent with C + + programming ideas, actually crashed, follow-up std::auto_ptr source, we see that 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 [1], how much will feel a bit unexpected.

After reading 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 result of the execution is:

Simple:1

Did you see anything unusual? The object we created was not refactored, and there was no output "~simple:1", causing a memory leak. When we don't want my_memory to survive, we call the release () function to free up memory, which results in a memory leak (in a memory constrained system, if my_memory takes up too much memory, we'll consider returning it immediately after use, rather than waiting until My_memory Return after the end of the life period).

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 (); Frees My_memory Internal managed memory

}

}

The original std::auto_ptr release () function simply conceded memory ownership, which is obviously not in line with C + + programming ideas.

Summary: Std::auto_ptr can be used to manage memory for a single object, but be aware of 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 release the object and only returns ownership.

(3) Std::auto_ptr It is best not to pass as a parameter (readers can write their own code to determine why not).

(4) Because of the "operator=" Problem of std::auto_ptr, the object of its management cannot be placed in std::vector and other containers.

(5) ...

There are a lot of restrictions on using a std::auto_ptr, and it's not enough to manage the heap memory array, which is what you're thinking about right now, and I think it's a lot of restrictions, and one of those days is an accident that causes problems.

Because STD::AUTO_PTR caused a lot of problems, some design is not very consistent with C + + programming ideas, so the following boost smart pointer, boost smart pointer can solve the above problem.

Let's keep looking down.

3, Boost::scoped_ptr

Boost::scoped_ptr belongs to the Boost library, defined in namespace boost, which 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, specifically, boost::scoped_ptr exclusive ownership, avoiding std::auto_ptr annoying 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 (); Compile error:scoped_ptr no release function

Std::auto_ptr<simple> My_memory2;

My_memory2 = my_memory; Compilation Error:scoped_ptr does not overload operator= and 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 deny users to write "My_memory2 = my_memory" and other statements, you can alleviate the std::auto_ptr a few annoying problems.

Because BOOST::SCOPED_PTR has exclusive ownership, when we really need to copy smart pointers, the requirements will not be satisfied, so we introduce a smart pointer, specifically to deal with the replication, parameter passing, this is the following boost::shared_ptr.

4, Boost::shared_ptr

Boost::shared_ptr belongs to the Boost library, defined in namespace boost, which contains header files #include <boost/smart_ptr.hpp> can be used. In the above we see BOOST::SCOPED_PTR exclusive ownership, not allow assignment, 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 by analyzing the 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 result of the execution is:

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 easily used. And there is no release () function. Crucially, Boost::shared_ptr maintains a reference count internally, which can support replication, parameter passing, and so on. Boost::shared_ptr provides a function Use_count (), which returns the reference count inside the boost::shared_ptr. Looking at the results of the execution, we can see that in the TESTSHAREDPTR2 function, the reference count is 1, the argument is passed (one copy here), inside the function testsharedptr, the reference count is 2, and after Testsharedptr returns, the reference count is reduced to 1. Boost::shared_ptr is no better when we need to use a shared object.

Here we have seen the smart pointer management of a single object, about smart pointer management arrays, which we'll cover next.

5, Boost::scoped_array

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

Boost::scoped_array is used to manage dynamic arrays. Same as Boost::scoped_ptr, but also exclusive ownership.

Let's start by analyzing the code:

void Testscopedarray () {

Boost::scoped_array<simple> my_memory (new simple[2]); class using an array of memory.

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"; Compiler error,scoped_ptr does not overload operator*

My_memory[0].release (); Ditto, no release function

Boost::scoped_array<simple> My_memory2;

My_memory2 = my_memory; Compile error, ditto, no overloaded operator=

}

}

The use of Boost::scoped_array is similar to that of Boost::scoped_ptr, which does not support replication and requires the use of dynamic arrays when initializing. In addition, Boost::scoped_array does not overload "operator*", in fact, this is not a major obstacle, in general, we use the Get () function more explicit.

The following must be 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 the Boost library, defined in namespace boost, which contains header files #include <boost/smart_ptr.hpp> can be used.

Due to boost::scoped_array exclusive ownership, obviously in many cases (parameter transfer, object assignment, etc.) do not meet the requirements, thus 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 00";

My_memory[0]. Printsomething ();

MY_MEMORY[1]. Printsomething ();

My_memory.get () [1].info_extend = "addition 11";

MY_MEMORY[1]. Printsomething ();

(*my_memory) [0].info_extend + = "other"; Compiler error,scoped_ptr does not overload 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 result of the execution is:

simple:0

simple:0

Printsomething:

printsomething:addition 00

Printsomething:

Printsomething:addition 11

TestSharedArray2 usecount:1

Testsharedarray Usecount:2

TestSharedArray2 usecount:1

~simple:0

~simple:0

Like Boost::shared_ptr, reference counts are used, which can be copied and passed through parameters.

So far, the smart pointers we've talked about are std::auto_ptr, Boost::scoped_ptr, Boost::shared_ptr, Boost::scoped_array, and Boost::shared_array. These smart pointers have been basically enough for us to use, and 90% of the code that used standard smart pointers is 5. There are two smart pointers, which are certainly useful, but what is the use of it?

7, Boost::weak_ptr

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

Before we talk about Boost::weak_ptr, let's review what we explained earlier. It seems boost::scoped_ptr, boost::shared_ptr these two smart pointers will be able to solve all the individual object memory management, there is a boost::weak_ptr, whether there are some circumstances we did 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 failure, the corresponding boost::weak_ptr also fails.

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 result of the execution is:

Simple:1

Testweakptr boost::shared_ptr usecount:1

Testweakptr boost::shared_ptr usecount:1

~simple:1

We see that, despite being assigned, there is no change in the internal reference count, and of course the reader can try other things such as passing parameters.

The question now is, what does boost::weak_ptr really do? 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 defined in the base class (where the base class is not an abstract base class, but refers to the virtual base class inherited from the abstract base class) to define a boost::weak_ptr for the child class Boost::shared_ptr, so that the base class just observe whether their own boost::weak_ptr is empty to know that the subclass has not assigned to itself, without affecting the subclass Boost::shared_ptr reference count, to reduce complexity, better management objects.

8, Boost::intrusive_ptr

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

After talking about the 6 kinds of smart pointers, the C + + heap memory management is enough for the general program, now there is a boost::intrusive_ptr, this is a kind of plug-in smart pointer, internal does not contain reference count, need the programmer to join the reference count, Otherwise compiled (⊙﹏⊙ b Khan). Personally, this smart pointer is not very useful, at least I didn't use it. Interested friends to study the source code Oh J.

Iii. Summary

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

1, in the case of the use of the boost library, refuse to use std::auto_ptr, because it is not only incompatible with C + + programming ideas, and very error-prone [2].

2. Use Boost::scoped_ptr (of course dynamic arrays using Boost::scoped_array) when determining that an object does not need to be shared.

3. Use Boost::shared_ptr if the object needs to be shared (the dynamic array, of course, uses Boost::shared_array).

4, in the case of need to access boost::shared_ptr object, but do not want to change its reference count, using 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 in the Delete keyword (or the C language of the free function), because you can use the smart pointer to manage.

---------------------------------------

[1] Refer to "Effective C + + (3rd)", Clause 06.

[2] Regarding the use of the Boost library, this blog can be another article: "Compiling boost1.42.0 in Windows".

[3] The reader should see, before all my names, are added the namespace identifier std:: (or Boost::), this is not I do not want to write using namespace XXX and other statements, in large projects, it is possible to use N third-party libraries, if the namespace all out, The problem of naming pollution (naming conflicts) is difficult to avoid, and it is extremely troublesome to change it back. Of course, if you just write the Demo, you can do the exception.

A C + + smart pointer

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.