Shared_ptr:
Shared_ptr is a "smart pointer" most like a pointer ".
Like scoped_ptr, shared_ptr encapsulates the dynamic objects allocated by the new operator on the stack. However, shared_ptr implements the reference of a counter-type smart pointer, which can be freely copied and assigned values, share it in any place. Only when no code is used (the reference count is 0) can it be used to delete the encapsulated dynamically assigned object. Shared_ptr can also be securely placed in the standard container, and makes up for the auto_ptr's defect that the pointer cannot be used as an STL container element because of the transfer semantics.
Operation functions:
Same features as scoped_ptr:
Shared_ptr and scoped_ptr are also smart pointers used to manage new dynamically assigned objects. Therefore, there are many functional similarities. They all reload the * and-> operators to mimic the behavior of the original pointer, implicit bool type conversion is provided to determine the validity of the pointer. Get () can obtain the original pointer without providing pointer arithmetic operations.
Different features from scoped_ptr:
Shared_ptr can be securely shared. It is a full-featured class with normal copy and assignment semantics. It can also be compared between shared_ptr and is the "most intelligent" smart pointer.
Shared_ptr has multiple forms of constructor, which can be applied to various possible situations:
[1] shared_ptr () without parameters creates a shared_ptr with null pointers;
[2] shared_ptr (y * P) is used to obtain the management right of the pointer P pointing to the type T, and the reference count is set to 1. This constructor requires that the T type must be converted to the T type.
[3] shared_ptr (shared_ptr const & R) obtains the pointer management right from another shared_ptr and Adds 1 to the reference count. The result is that the two shared_ptr share the management right of a pointer.
[4] shared_ptr (STD: auto_ptr <Y> & R) obtains the pointer management right from an auto_ptr, sets the reference count to 1, and auto_ptr automatically loses the management right.
[5] OPERATOR = the assignment operator can obtain the pointer management right from another shared_ptr or auto_ptr, and its behavior is the same as that of the constructor;
[6] shared_ptr (y * P, d) behavior is similar to shared_ptr (y * P), but the parameter D is used to specify the custom Delete tool for the structure, rather than simple Delete.
The reset () function of shared_ptr does not act in the same way as scoped_ptr. It is used to reduce the reference count by 1 and stop sharing the pointer unless the reference count is 0, otherwise, the delete operation will not be sent. The reset () with parameters is similar to the constructor in the same form. The original pointer references the Count minus 1 and changes it to manage another pointer.
Shared_ptr has two special functions to check the reference count. Unique () returns true when shared_ptr is the unique owner of the pointer (in this case, shared_ptr acts like auto_ptr or scoped_ptr), use_count () return the reference count of the current pointer. Be careful. use_count () should only be used for testing or debugging. It does not provide efficient operations and may be unavailable in some cases ). Unique () is reliable and can be used at any time, and is faster than use_count () = 1.
Shared_ptr also supports comparison operations. You can test whether two shared_ptr values are equal or not. The comparison is based on internally saved pointers, which is equivalent to. get () = B. get (). shared_ptr can also use operator <to compare the size. It is also based on internally saved pointers, but does not provide comparison operators other than operator <, this allows shared_ptr to be used in standard associated containers (set and map );
The type conversion of pointers is useful when writing multi-state code based on virtual functions. For example, converting a base class pointer to a subclass pointer or vice versa, however, for shared_ptr, such as static_cast <t *> (P. get (), which prevents the transformed pointer from being correctly managed by shared_ptr. To support this usage, shared_ptr provides a transformation function like static_pointer_cast <t> (), const_pointer_cast <t> () and dynamic_pointer_cast <t> () are similar to standard transformation operators static_cast <t>, const_cast <t>, and dynamic_cast <t>, however, shared_ptr after transformation is returned.
Shared_ptr also supports the stream output Operator <, which outputs internal pointer values for convenient debugging.
Usage:
Shared_ptr also provides basic thread security guarantee. A shared_ptr can be securely read by multiple threads, but other access results are undefined.
Factory functions:
Shared_ptr provides a free factory function (located in the boost namespace) make_shared <t> () in the header file <boost/make_shared.hpp> to eliminate explicit new calls, its name imitates make_pair () of the standard library ();
Template <class T, class... ARGs>
Shared_ptr <t> make_shared (ARGs &... ARGs );
The make_shared () function can accept a maximum of 10 parameters, pass them to the T-Type constructor, create a shared_ptr <t> object, and return the result. Make_shared () functions are faster and more efficient than directly creating shared_ptr objects, because they only allocate memory once internally, eliminating the overhead during shared_ptr construction.
Code example:
# Include <iostream>
# Include <vector>
# Include <boost/make_shared.hpp>
Using namespace boost;
Using namespace STD;
Int _ tmain (INT argc, _ tchar * argv [])
{
Shared_ptr <string> sp = make_shared <string> ("make_shared"); // create a string shared pointer
Shared_ptr <vector <int> SPV = make_shared <vector <int> (); // create a shared pointer for a vector
Assert (SPV-> size () = 10 );
Return 0;
}
In addition to make_shared (), the smart_ptr Library also provides a allocate_shared (), which accepts a custom memory Distributor Type parameter more than make_shared.
Used in standard containers:
There are two ways to apply shared_ptr to standard containers (or other containers such as container adapters ).
One usage is to use a container as a shared_ptr management object, such as shared_ptr <list <t>, so that the container can be securely shared. Its usage is no different from that of common shared_ptr.
Another method is to use shared_ptr as a container element, such as vector <shared_ptr <t>. Because shared_ptr supports copy semantics and comparison operations, it meets the requirements of standard containers for elements, therefore, you can securely hold the pointer of elements in the container instead of copying them.
The standard container cannot accommodate auto_ptr, which is specified by the C ++ standard.
Standard containers cannot accommodate scoped_ptr, because scoped_ptr cannot be copied and assigned values.
The standard container can accommodate the original pointer, but this loses many of the benefits of the container, because the standard container cannot automatically manage elements with the pointer type, you must write a large amount of code to ensure that the pointer is deleted correctly.
The container storing shared_ptr has almost the same functionality as the container storing the original pointer. However, shared_ptr manages pointers for programmers and can use shared_ptr without worrying about resource leakage.
Code example:
# Include <iostream>
# Include <vector>
# Include <boost/make_shared.hpp>
Using namespace boost;
Using namespace STD;
Int _ tmain (INT argc, _ tchar * argv [])
{
Typedef vector <shared_ptr <int> vs; // a standard container type with a specific shared_ptr
Vs V (10); // declare a container with 10 elements.
// The Initialization is a null pointer.
Int I = 0;
For (vs: iterator Pos = V. Begin (); pos! = V. End (); ++ POS)
{
(* POS) = make_shared <int> (++ I); // use the factory function to assign values.
Cout <* (* POS) <",";
}
Cout <Endl;
Shared_ptr <int> P = V [9];
* P = 100;
Cout <* V [9] <Endl;
Return 0;
}
Bridging Mode:
Bridge is a structural design model that hides the implementation details of a class from users to achieve the minimum coupling between classes. In specific programming practices, the bridge mode is also called pimpl or handle/body. It can minimize the dependency between header files and reduce the Compilation Time, additionally, you can implement polymorphism without using virtual functions.
Apply to factory mode:
The engineering mode is a creation design mode. This mode encapsulates the use of the new operator, so that the object creation is concentrated in the factory class or factory function, so that it is easier to adapt to changes, make_shared () is a good example of the factory model.
Custom delimiters:
The first parameter of shared_ptr (y * P, d) is the pointer to be managed. It has the same meaning as other constructor parameters, the second deleteer parameter D tells shared_ptr not to use the delete operation pointer P in the structure, but to use D for the operation, that is, to replace Delete P with d (P );
Here, the deletable D can be a function object or a function pointer, as long as it can be called as a function, so that d (P) can be set up. The deletemediactor must be copyable, and its behavior must be the same as that of Delete. Exceptions cannot be thrown.
With the delete tool concept, you can use shared_ptr to manage any resources. As long as the resource provides its own release operation, shared_ptr can ensure automatic release.
The shared_ptr deleteer is very useful when processing some special resources. It allows users to customize and expand shared_ptr behavior so that shared_ptr can not only manage memory resources, it becomes a "omnipotent" resource management tool.
Advanced topics:
Shared_ptr <void>
Shared_ptr <void> can store void * pointers, while void * pointers can point to any type. Therefore, shared_ptr <void> is like a generic pointer container, it can accommodate any type of data.
Advanced use of the deleteer:
Based on shared_ptr <void> and the custom deleteer, shared_ptr can have even more amazing usage. Because a null pointer can make any pointer type, shared_ptr <void> can also call any function when exiting the scope. For example:
Void any_func (void * P) // a function that can execute any function
{
Cout <"Some operate" <Endl;
}
Int main ()
{
Shared_ptr <void> P (void *) 0, any_func); // contains null pointers and customizes deletors.
// When exiting the scope, any_func () will be executed ()
}
Shared_ptr <void> stores a null pointer and specifies that the deleteer is a function used to operate void *. Therefore, the any_func () function is automatically called during the analysis (), to execute whatever work we want to do.