Summary of four kinds of intelligent pointers used in STL Auto_ptr,unique_ptr,shared_ptr,weak_ptr

Source: Internet
Author: User
Tags assert throw exception
Was asked in an interview the use of four kinds of smart pointers in STL
Because of lack of experience, I only know auto_ptr and shared_ptr, and then said a weak ... Then the interviewer's cue was weak_ptr, and then he took the initiative to say Unique_ptr
I only did a bit of use for auto_ptr and shared_ptr.
Now in retrospect, the interview is still very dissatisfied with their own knowledge is also very dissatisfied, the recent work is not very busy, specifically to sum up the four kinds of smart pointers
In order to avoid the same mistakes in the future, it is a learning note.


1. auto_ptr
Auto_ptr is mainly used to solve the problem of automatic resource release, such as the following code:
void Function ()
{
Obj*p = new OBJ (20);
...
if (Error Occor)
Throw ... or Retrun;
Delete p;
}
After a function encounters an error, it usually throws an exception, or returns, but it is very likely that the previously requested resources will be omitted, and it is possible for a very experienced programmer to have this error.
Using auto_ptr, however, will release resources in its own function of analysis. Which is called Raii.
Use the AUTO_PTR code as follows
void Function ()
{
Auto_ptr<obj> ptr (new OBJ (20));
...
if (Error occur)
Throw exception ...
}
This will automatically release the resource regardless of whether the function has an exception or where it is returned.
What needs to be mentioned is that this is a smart pointer discarded by the C++11 standard, why it is discarded, first look at the following code:
Auto_ptr<obj> ptr1 (New OBJ ());
Ptr1->funca ();
auto_ptr<obj> ptr2 = ptr1;
Ptr2->funca ();
Ptr1->funca (); This sentence will be abnormal
Why after the ptr1 copy to PTR2 after PTR1 again use is unusual.
This is also the main reason why he was abandoned.
Because the transfer of a really referenced memory pointer in the AUTO_PTR copy constructor, that is, from PTR1 to PTR2, the PTR2 references the obj memory address, and the memory address referenced by PTR1 is empty,
The use of PTR1 at this time is abnormal.


2. Unique_ptr
Unique_ptr can be seen as a substitute for auto_ptr. Because his ownership of the object is more single-minded, so that the unique laugh
i) cannot replicate construction and assignment operations
Comparison of Auto_ptr and unique_ptr:
Auto_ptr<obj> ap (New OBJ ());
Auto_ptr<obj> one (AP); Ok
Auto_ptr<obj> two = one; Ok


Unique_ptr<obj> ap (New OBJ ());
Unique_ptr<obj> one (AP); can go wrong
Unique_ptr<obj> two = one; can go wrong
That is to say, unique_ptr the object of the reference is more single-minded, do not allow casual transfer
II can move construction and move assignment operations
Unique_ptr<obj> Getobj ()
{
Unique<obj> ptr (New OBJ ());
return ptr;
}
unique<obj> ptr = Getobj ();
The code above can be executed smoothly.
What is move construction and move assignment? This benefits from the C++11 standard specification. This knowledge point can refer to the third of the reference Web site.
So what if I just need to assign a UNIQUE_PTR smart pointer to the other one?
You can use the Move function. As follows:
Unique<obj> ptr1 (New OBJ ());
Unique<obj> ptr2 (Std::move (PTR1));
This effect is the same as Auto_ptr direct assignment, that is, PTR1 no longer owns the Obj object, so ptr1 can no longer be used to manipulate the Obj object in memory because it is manually operated,
So programmers themselves will be more careful.


3. shared_ptr
Auto_ptr and Unique_ptr can only reference objects with one smart pointer, and shared_ptr can have multiple smart pointers at the same time.
The shared_ptr implementation is to use reference counting. This technique is used in COM as a way to manage the lifecycle of COM objects.
The principle of reference counting is that multiple smart pointers refer to an object at the same time, each time the reference count is added, and whenever the smart pointer is destroyed, the reference count is reduced by one.
The referenced object is released when the reference count is reduced to 0. The increase or decrease of this reference count occurs in the constructor function of the smart pointer, the copy constructor, the assignment operator, and the destructor.
This approach allows multiple smart pointers to have ownership of the referenced object at the same time, and automatically frees up memory after the reference count is reduced to 0, as well as the ability to release the auto_ptr and Unique_ptr resources.


void Function ()
{
Shared_ptr<obj> ptr1 (New OBJ ()); Reference count is 1
{
Shared_ptr<obj> ptr2 (PTR1); Reference count is 2
{
shared_ptr<obj> PTR3 = PTR2; Reference count is 3
int e = 0
}
Reference count is 2
}
Reference count is 1
}
Obj memory with a reference count of 0,new after the function returns has been released


Because shared_ptr supports a copy construct, he can act as an element in a standard container
Vector<shared_ptr<obj>> Vect;
for (int i = 0; i < ++i)
{
Vect.push_back (New OBJ ()) (shared_ptr<obj>);
}
vector<shared_ptr<obj>> vect2 = Vect;
These operations are auto_ptr and UNIQUE_PTR cannot be implemented.
Note that the smart pointer uses delete to release resources by default, if the resource is file*. The release of the time will need to use fclose.
How to achieve it.
The shared_ptr constructor can pass a delete.
file* PStm = fopen (...);
Shared_ptr<file> fileres (PStm, &fclose);
Or use an imitation function
Class Filecloser {
Public


void operator () (file* FILE) {


Std::cout << "The Filecloser has been called with a file*,"


"Which'll now is closed.\n";


if (file!=0)


fclose (file);


}


};
Shared_ptr<file> fileres (PStm, Filecloser);
See this article for a reference: http://www.cnblogs.com/learn-my-life/p/3817151.html




4. weak_ptr
SHARED_PTR is a strongly referenced relationship, and the smart pointer refers directly to the object. Then the implicit problem with this code is that it's circular references, causing a memory leak, even if the Java language has its own
Garbage collector, there is no way to do this memory leak, so circular references are also a noteworthy issue for Java programmers. First, let's look at an example of a circular reference.


Class Parent
{
Public
Shared_ptr<child> child;
};




Class Child
{
Public
Shared_ptr<parent> Parent;
};


void Function ()
{
Shared_ptr<parent> PA (new Parent);
Shared_ptr<child> PB (new child);
Pa->child = PB;
Pb->parent = PA;
}
Now let's analyze the execution of function functions:
1. The first statement makes the PA reference a pointer to parent, and the parent reference count is 1
2. The second statement makes PB reference a pointer to the child, and a child reference count of 1
3. The third statement, which invokes the assignment operator of the Shared_ptr<child> class, makes the child reference count into 2
4. The fourth statement, calling the assignment operator of the Shared_ptr<parent> class, makes the Parent reference count to 2
5. Function returned before calling the Shared_ptr<parent> and shared_ptr<child> classes, making the child reference count into 1,parent reference count to 1
See. The new parent and child were not released after the function was executed, so a memory leak occurred.
The reason for the leak is that the PA and PB cross-reference each other, resulting in the reference count of both objects can not be reduced to 0, resulting in a leak.
If you delete the third statement or the fourth statement arbitrarily, there will be no leakage.
This is the problem with strong references.
Weak_ptr can be seen literally as a weak pointer, not a weaker ability to describe the pointer, but rather a weaker ownership of the object he refers to.
To be more direct, he does not have ownership of the referenced object, and he cannot directly use the object he refers to.


In the STL, WEAK_PTR is used in conjunction with shared_ptr, in the realization of shared_ptr time also considered the weak_ptr factor.
WEAK_PTR is a shared_ptr observer who does not interfere with the ownership of objects shared by shared_ptr
When a weak_ptr observes shared_ptr to release its resources, it sets the associated weak_ptr pointer to null to prevent weak_ptr from holding dangling pointers.
Note: Weak_ptr does not have ownership of resources, so resources cannot be used directly.
You can construct a shared_ptr from a weak_ptr to take ownership of a shared resource.
void Function ()
{
Shared_ptr<int> sp (new OBJ ());
ASSERT (sp.use_count () = = 1);
weak_ptr<int> wp (SP); Create Weak_ptr from shared_ptr
ASSERT (wp.use_count () = = 1);
if (!wp.expired ())//To determine whether the object weak_ptr observed is invalid
{
Shared_ptr<int> SP2 = Wp.lock ();//Get a shared_ptr
*SP2 = 100;
ASSERT (wp.use_count () = = 2);
}
ASSERT (wp.use_count () = = 1);
return 0;
}
WEAK_PTR does not overload the-> and * operators, so we can't use the resources directly from him, we can get a shared_ptr object by lock
To use the resource, and if the referenced resource has been freed, the lock () function returns a shared_ptr that stores the null pointer. The expired function is used to determine whether a resource is invalidated.
Using weak_ptr does not increase the reference count of resources. Therefore, references to resources are weak references, which can be used to solve the problem of cyclic dependencies mentioned earlier.


Class Parent
{
Public
Weak_ptr<child> child;
};




Class Child
{
Public
Weak_ptr<parent> Parent;
};


void Function ()
{
Shared_ptr<parent> PA (new Parent);
Shared_ptr<child> PB (new child);
Pa->child = PB;
Pb->parent = PA;
}


This time the execution of the third and fourth statements does not increase the reference count, so that only memory can be freed automatically when the function is executed.
From the above analysis, we can see that weak_ptr is an auxiliary shared_ptr of a kind of intelligent pointers, generally not used alone, but the combination
Shared_ptr used together.


Summarize:
1. Use unique_ptr as much as possible instead of using auto_ptr
2. Generally speaking, shared_ptr can meet most of our needs.
3. weak_ptr can avoid recursive dependencies


Reference URL:
1. http://www.jellythink.com/archives/684
2. http://www.jellythink.com/archives/673
3. http://www.cnblogs.com/TianFang/archive/2013/01/26/2878356.html (c + + right value reference related knowledge point)
4. http://www.cnblogs.com/learn-my-life/p/3817151.html
5. http://blog.csdn.net/hp_truth/article/details/40511617
6. http://www.cppblog.com/deane/archive/2010/02/25/108428.html (c + + temporary object related knowledge point)
7. http://blog.csdn.net/mmzsyx/article/details/8090849
8. http://www.cnblogs.com/learn-my-life/p/3817279.html

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.