Introduction
Memory Management has always been a complicated problem in C ++, but smart pointers can solve this problem well and have been scheduled to be deleted during initialization, solving the worries. The first version of the C ++ standard revised in 1998 only provides a smart pointer: STD: auto_ptr (currently obsolete), which is basically like a common pointer: access a dynamically allocated object through an address. STD: auto_ptr is regarded as a smart pointer because it will call the delete operator to automatically release the contained objects during structure analysis. Of course, this requires that the object address returned by the new operator be transmitted during initialization. Since the destructor of STD: auto_ptr calls the delete operator, the memory of the objects it contains will be released. This is an advantage of smart pointers.
This is even more important when you try to associate with exceptions: Without smart pointers like STD: auto_ptr, every function that dynamically allocates memory needs to capture all possible exceptions, to ensure that the memory is released before the exception is passed to the caller of the function. The boost C ++ library's smart pointer series provides many smart pointers that can be used in various occasions.
RaiI
The full name of raiI is "resource acquisition is initialization ". However, this translation does not show the true meaning of this idiom. RaiI provides a method for automatic resource management. When exceptions or rollback occurs, raiI can release resources correctly.
RaiI is also the basic principle of smart pointers. Smart pointers are just one of these idioms. Smart pointers ensure that the dynamically allocated memory can be correctly released under any circumstances, freeing developers from this task. This includes scenarios where the program is interrupted due to exceptions and the code originally used to release the memory is skipped. Use the address of a dynamically allocated object to initialize the smart pointer. This is ensured when the memory is released during the analysis. Because the Destructor will always be executed, so that the contained memory will always be released.
Many C ++ applications require dynamic memory management. Therefore, smart pointers are a very important type of raiI, but raiI itself is applicable to many other scenarios.
Scoped_ptr
Boost: scoped_ptr is a simple smart pointer that can ensure that the object is automatically released after it leaves the scope.
Boost: scoped_ptr uses the objects on a stack to manage objects on a stack, so that the objects on the stack are automatically deleted when the objects on the stack are destroyed.
Boost: scoped_ptr features
- Cannot change ownership
The object lifecycle managed by scoped_ptr is limited to only one interval (between "{}" where the pointer is located) and cannot be passed out of the interval, this means that the scoped_ptr object cannot be returned as a function.
- Cannot share ownership
This feature makes the pointer easy to use. On the other hand, it also causes weak functionality: it cannot be used in STL containers.
- Cannot be used to manage array objects
Because scoped_ptr deletes the managed object through delete, and the array object must be deleted through deletep [], scoped_ptr cannot manage the array object, to manage array objects, use the boost: scoped_array class.
Shared_ptr
Boost: Although scoped_ptr is easy to use, its ability to share ownership is greatly restricted. shared_ptr can solve this limitation. STD: shared_ptr in the Standard C ++ library. In the boost C ++ library, the smart pointer is named boost: shared_ptr.
The shared_ptr management mechanism is not complex, that is, the reference count of the managed object is performed. When a shared_ptr is added to manage the object, the reference count of the object is added; when a shared_ptr is reduced to manage the object, the reference count of the object is reduced by one. If the reference count of the object is 0, no pointer is managed, call Delete to release the memory occupied by it.
Boost: shared_ptr features
- Share Object ownership
Compared with scoped_ptr, shared_ptr can share the ownership of objects. Therefore, the copies stored in the container (including the additional copies created by the container when needed) are the same as those of the original, you can safely use dynamically assigned objects in standard containers.
- Thread-safe
The shared_ptr object provides the same thread security level as the built-in type. A shared_ptr instance can be "read" by multiple threads at the same time (accessed only using unchanged operations ). Different shared_ptr instances can be "written" by multiple threads at the same time (accessed using variable operations like operator = or reset) (even if these instances are copies, and the reference count of the shared lower layer ). Any other concurrent access results will lead to undefined behavior ."
- It is safe that the same shared_ptr is "read" by multiple threads.
- It is not safe that the same shared_ptr is "written" by multiple threads.
- Different shared_ptr of shared reference count are "written" by multiple threads.
- Supports custom deleter
Boost: shared_ptr considerations
- Shared_ptr can be used as a function parameter or a function return value. At this time, it is equivalent to using the copy structure.
- Shared_ptr can be used in standard containers. during replication, it is equivalent to using replication construction.
- Be sure not to reference them cyclically. This will prevent objects from being released.
Weak_ptr
Shared_ptr reference counting is a convenient memory management mechanism, but it has a major drawback, that is, it cannot manage objects that are referenced cyclically. For example:
#include <string>#include <iostream>#include <boost/shared_ptr.hpp>#include <boost/weak_ptr.hpp>class parent;class children;typedef boost::shared_ptr<parent> parent_ptr;typedef boost::shared_ptr<children> children_ptr;class parent{public: ~parent() { std::cout <<"destroying parent\n"; }public: children_ptr children;};class children{public: ~children() { std::cout <<"destroying children\n"; }public: parent_ptr parent;};void test(){ parent_ptr father(new parent()); children_ptr son(new children); father->children = son; son->parent = father;}void main(){ std::cout<<"begin test...\n"; test(); std::cout<<"end test.\n";}
After running this program, we can see that even after the test function is exited, since the parent and children objects reference each other, their reference count is 1 and cannot be released automatically, in this case, these two objects cannot be accessed, which causes memory leakage.
In general, there are three feasible methods to remove such circular references:
- When only the last reference is left, you need to manually break the circular reference to release the object.
- When the lifetime of parent exceeds the lifetime of Children, Children uses a normal pointer to point to parent.
- Use a smart pointer with weak references to break this type of circular reference. Strong references are used for parent-child references, and weak references are used for parent-child references to avoid circular references.
Although these three methods are feasible, both method 1 and method 2 require manual control by programmers, Which is troublesome and error-prone. Here we will mainly introduce the third method and the smart pointer boost: weak_ptr, which is a weak reference in boost.
Strong reference
A strong reference when the referenced object is still alive, this reference also exists (that is, when at least one strong reference exists, this object cannot be released ). Boost: share_ptr is strongly referenced.
Weak reference
It is only a reference when an object exists. When the object does not exist, the weak reference can be detected to avoid unauthorized access. The weak reference does not modify the reference count of the object. This means that the weak reference does not manage the memory of the object, and is similar to a common pointer in function. However, a big difference is that, the weak reference can detect whether the managed object has been released, thus avoiding unauthorized access to the memory.
In C ++, common pointers can be seen as weak references, and smart pointers can be seen as strong references. Although pointers cannot be regarded as "real" weak references, because the weak reference should be able to know when the object becomes inaccessible.
Break loop reference
Strong references are used for parent-child references, and weak references are used for parent-child references to avoid circular references.
// For a detailed example, see boost smart pointer-weak_ptrclass children {public :~ Children () {STD: cout <"destroying children \ n";} public: boost: weak_ptr <parent> parent ;};
Although the weak reference pointer can effectively remove the circular reference, this method must be used only when the programmer can foresee the circular reference, it can also be said that this is only a solution during the compilation period. If the program appears loop reference during the running process, it will still cause memory leakage.
Intrusive_ptr
In most cases, we do not use boost: intrusive_ptr because the shared ownership feature is provided in boost: shared_ptr, and non-plug smart pointers are more flexible than plug-in smart pointers.
However, sometimes you also need to insert the reference count, probably because of the old Code or to integrate with a third-party class. If this is needed, you can use intrusive_ptr, which has the same semantics as other boost smart pointers. If you have used other boost smart pointers, you will find that all smart pointers have consistent interfaces no matter whether they are plug-in or not.
The class that uses intrusive_ptr must provide reference counts. Intrusive_ptr manages the reference count by calling two functions, intrusive_ptr_add_ref and intrusive_ptr_release. These two functions must correctly operate the inserted reference count to ensure that intrusive_ptr works correctly. When the intrusive_ptr class has a built-in reference count, the support for intrusive_ptr is to implement these two functions. In some cases, you can create parameterized versions of these two functions, and then use the same implementation for all types with plug-in reference counts. Most of the time, the best place to declare these two functions is the namespace of the types they support.Use intrusive_ptr in the following cases
- Use this as a smart pointer.
- Existing Code uses or provides plug-in reference count.
- The size of the smart pointer must be equal to that of the bare pointer.
Boost: shared_ptr
To use the boost: shared_ptr user class, you do not need to have the reference counting function in this province. Instead, it is provided by boost: shared_ptr. Use boost :: A major trap of shared_ptr is to use a raw pointer to create boost: shared_ptr multiple times. This will cause the raw pointer to be destroyed multiple times when boost: shared_ptr is parsed. That is, it cannot be used as follows:
Int * A = new int (5); Boost: shared_ptr ptr1 (a); Boost: shared_ptr ptr2 (a); // error!
Boost: intrusive_ptr is fully equipped with the boost: shared_ptr function, and there is no shared_ptr problem, that is, you can use raw pointer to create multiple intrusive _ PTR, because it refers to the ref_count object of the count, shared_ptr is placed in the shared_ptr structure, and the target object t uses the reference count as the internal member variable of the t object by inheriting intrusive_ptr_base, so that there are no two reference counters for the same object.
So why do we usually encourage you to use shared_ptr instead of intrusive_ptr? shared_ptr is not invasive and can point to any type of object. The object to which intrusive_ptr points must inherit intrusive_ptr_base, the reference counting member is also created.
Reference
Http://zh.wikipedia.org/wiki/%E5%BC%B1%E5%BC%95%E7%94%A8 http://www.codeproject.com/Articles/8394/Smart-Pointers-to-boost-your-code http://www.cnblogs.com/TianFang/archive/2008/09/15/1291050.html http://www.cnblogs.com/TianFang/archive/2008/09/19/1294521.html http://www.cnblogs.com/TianFang/archive/2008/09/20/1294590.html http://blog.csdn.net/alai04/article/details/572959 http://blog.csdn.net/yockie/article/details/8840205 http://blog.csdn.net/juana1/article/details/6624222 http://blog.csdn.net/ithzhang/article/details/9038929 http://blog.csdn.net/hunter8777/article/details/6327704
From: http://blog.csdn.net/liufei_learning/article/details/34808549