Use of the smart pointer shared_ptr component

Source: Internet
Author: User

Shared_ptr is the most valuable and important component in the boost. smart_ptr library. Like scoped_ptr, it encapsulates the new operator to allocate dynamic objects on the stack, But it implements a reference-count smart pointer that can be freely copied and assigned values, share it anywhere. When the reference count value is 0, that is, if no code is used, it will automatically delete the objects of the allocated resources.

Shared_ptr can be securely placed in the standard container, and makes up for the auto_ptr's defect that the pointer STL container element cannot be transferred because of the transfer semantics. C ++ has seen many reference-counting smart pointers in history, but none of them are comparable to boost: shared_ptr. In the past, now, it will be the best in the future.

Class Abstract:
template<class T> class shared_ptr{private:    // Borland 5.5.1 specific workaround    typedef shared_ptr<T> this_type;public:    typedef T element_type;    typedef T value_type;    typedef T * pointer;    typedef typename boost::detail::shared_ptr_traits<T>::reference reference;    shared_ptr();    template<class Y>    explicit shared_ptr( Y * p );    template<class Y, class D> shared_ptr(Y * p, D d);    template<class Y, class D, class A> shared_ptr( Y * p, D d, A a );    template<class Y>    explicit shared_ptr(weak_ptr<Y> const & r);    template<class Y>    shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag );    template<class Y>    shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() );    shared_ptr( shared_ptr<Y> const & r );    template< class Y >    shared_ptr( shared_ptr<Y> const & r, T * p );    template<class Y>    shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag);    template<class Y>    shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag);    template<class Y>    shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag);    template<class Y>    shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag);    template<class Y>    explicit shared_ptr(std::auto_ptr<Y> & r);    template<class Ap>    explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 );    shared_ptr & operator=( shared_ptr const & r ) // never throws    template<class Y>    shared_ptr & operator=(shared_ptr<Y> const & r) //never throw    template<class Y>    shared_ptr & operator=( std::auto_ptr<Y> & r );    template<class Ap>    typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r );    shared_ptr( shared_ptr && r );    template<class Y>    shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )    shared_ptr( shared_ptr<Y> && r );    shared_ptr & operator=( shared_ptr && r ); // never throws     template<class Y>    shared_ptr & operator=( shared_ptr<Y> && r ) // never throws    void reset() ;// never throws in 1.30+    template<class Y> void reset(Y * p) // Y must be complete    template<class Y, class D> void reset( Y * p, D d );    template<class Y, class D, class A> void reset( Y * p, D d, A a );    template<class Y> void reset( shared_ptr<Y> const & r, T * p );    reference operator* () const;// never throws    T * operator-> () const; // never throws    T * get() const;// never throws    bool unique() const; // never throws    long use_count(); const // never throws    void swap(shared_ptr<T> & other);// never throws    template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const;    void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti );    bool _internal_equiv( shared_ptr const & r ) const;private:    template<class Y> friend class shared_ptr;    template<class Y> friend class weak_ptr;    T * px;                     // contained pointer    boost::detail::shared_count pn;    // reference counter};  // shared_ptr

Shared_ptr reloads the * and-> operators to mimic the behavior of the original pointer, and provides implicit bool type conversion to determine whether the pointer is valid. Get () can get the original pointer without providing pointer arithmetic operations. It can copy, assign values, or compare 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) obtains the management right of pointer P pointing to type T, and sets the reference count to 1. This constructor requires that the T type be converted to the Y type.

3. shared_ptr (shared_ptr const & R) obtains the pointer management right from another shared_ptr, and the reference count is 1. The result is that two shared_ptr share the management right of one pointer.

4. shared_ptr (STD: auto <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. The shared_ptr (y * P, d) behavior is similar to shared_ptr (y * P). However, the parameter D is used to specify the custom Delete tool for the destructor, rather than the simple Delete tool.

 

Shared_ptr's reset () function is to reduce the reference count by 1 and stop sharing the pointer. Unless the reference count is 0, no deletion operation will be performed. 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 functions to check the reference count. Unique () returns true when shared_ptr is the unique owner of the pointer (the behavior is similar to auto_ptr or scoped_ptr), use_count () returns the reference count of the current pointer. But be careful, use_count () is only used for testing or debugging. It does not provide efficient operations and may sometimes be unavailable. However, unique () is reliable and can be used at any time, and is faster than use_count () = 1.

Shared_ptr supports comparison. You can test whether two shared_ptr values are equal or not equal. The comparison is based on internally saved pointers, which is equivalent to a. Get () = B. Get (). You can also use operator <to compare the size, which is also based on the internally saved pointer, but does not provide a comparison character other than it, so that shared_ptr can be applied to standard associated containers (set and map ):

Typedef shared_ptr <string> sp_t;

Map <sp_t, int> m; // standard ing container

Sp_t Sp (new string ("one "));

M [Sp] = 111;

The type conversion of pointers is useful when writing multi-state code based on virtual functions, such as converting a base class pointer to an inherited class pointer or vice versa (converting an inherited class pointer to a base class pointer ). However, shared_ptr cannot use a format such as static_cast <t *> (P. Get. This will cause the transformed pointer to be incorrectly managed by shared_ptr. To support this usage, shared_ptr provides transformation functions like static_pointer_cast <t> (), const_pointer_cast <t>, and dynamic_pointer_cast <t>, but returns shared_ptr after transformation.

For example, the following code uses dynamic_pointer_cast to convert a shared_ptr <STD: exception> down to a shared_ptr <bad_exception>, and then uses static_pointer_cast to reset it to shared_ptr <STD: exception>;

Shared_ptr <STD: exception> SP1 (New bad_exception ("error "));

Shared_ptr <bad_exception> SP2 = dynamic_pointer_cast <bad_exception> (SP1 );

Shared_ptr <STD: exception> SP3 = static_pointer_cast <STD: exception> (SP2 );

Assert (SP3 = SP1 );

Shared_ptr also supports the stream output Operator <, which outputs internal pointer values for convenient debugging.

 

Example:

#include <iostream>#include <boost/smart_ptr.hpp>using namespace boost;using namespace std;class shared //define a custom class{ public: shared(shared_ptr<int> p):_p(p){} void print() {  cout << "count: " << _p.use_count()       << "  v= " << *_p << endl; } private: shared_ptr<int> _p;};void print_func(shared_ptr<int> p){ cout << "count: " << p.use_count()       << "  v= " << *p << endl;}int main(){ /* /*example1 shared_ptr<int> sp(new int(10));//a smart_ptr pointed to int assert(sp.unique()); //shared_ptr is the only owner of pointer  shared_ptr<int> sp2 = sp; //the second shared_ptr,copy construct assert(sp == sp2 && sp.use_count() == 2);  //Two shared_ptr equal, pointing in the same object, reference counting is 2 *sp2 = 100; //now print *sp2 assert(*sp == 100); sp.reset();// assert(!sp);//sp now is empty cout << "no problem." << endl;     */ /*example2*/ shared_ptr<int> p(new int(100)); shared s1(p),s2(p);//custom shared class object  s1.print(); //3 s2.print();//3  *p = 20; //modify the value of the object which p point to print_func(p);//display use_count 4 s1.print();//3 }

 

Running result:

Count: 3 V = 100
Count: 3 V = 100
Count: 4 V = 20
Count: 3 V = 20

Note: We do not use the reference method to pass the parameter, but directly copy it. It is like using an original pointer. shared_ptr supports this usage.

After the cmd_ptr and two shared class instances are declared, the pointer is shared by them, so the reference count is 3. The print_fun () function copies a shared_ptr object internally, so the reference count is increased by 1. When exiting, the copy function automatically analyzes the structure, and the reference count is restored to 3.

 

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.