# Class shared_ptr

Introduction
Synopsis
Members
Example
Handle/Body Idiom
Frequently Asked Questions
Smart Pointer Timings

## Introduction

Class shared_ptr stores a pointer to a dynamically allocated object. (Dynamically allocated objects are allocated with the C++ `new` expression.) The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to it is deleted or reset. See example.

Class shared_ptr meets the CopyConstuctible and Assignable requirements of the C++ Standard Library, and so can be used in C++ Standard Library containers. A specialization of std:: less< > for boost::shared_ptr<Y> is supplied so that shared_ptr works by default for Standard Library's Associative Container Compare template parameter. For compilers not supporting partial specialization, the user must explicitly pass the less<> functor.

Class shared_ptr cannot correctly hold a pointer to a dynamically allocated array. See shared_array for that usage.

Class shared_ptr will not work correctly with cyclic data structures. For example, if main() holds a shared_ptr to object A, which directly or indirectly holds a shared_ptr back to object A, then object A's use_count() will be 2, and destruction of the main() shared_ptr will leave object A dangling with a use_count() of 1.

The class is a template parameterized on `T`, the type of the object pointed to. `T` must meet the smart pointer Common requirements.

## Class shared_ptr Synopsis

    #include <boost/smart_ptr.hpp>
    namespace boost {

    template<typename T> class shared_ptr {

     public:
       typedef T element_type;

       explicit shared_ptr( T* p=0 );
       ~shared_ptr();

       shared_ptr( const shared_ptr& );
       template<typename Y>
          shared_ptr(const shared_ptr<Y>& r);  // never throws
       template<typename Y>
          shared_ptr(std::auto_ptr<Y>& r);

       shared_ptr& operator=( const shared_ptr& );  // never throws
       template<typename Y>
          shared_ptr& operator=(const shared_ptr<Y>& r);  // never throws
       template<typename Y>
          shared_ptr& operator=(std::auto_ptr<Y>& r);

       void reset( T* p=0 );

       T& operator*() const;  // never throws
       T* operator->() const;  // never throws
       T* get() const;  // never throws

       long use_count() const;  // never throws
       bool unique() const;  // never throws

       void swap( shared_ptr<T>& other ) throw()
       };

    template<typename T, typename U>
      inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
        { return a.get() == b.get(); }

    template<typename T, typename U>
      inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
        { return a.get() != b.get(); }
    }

    namespace std {

    template<typename T>
      inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
        { a.swap(b); }

    template<typename T>
      struct less< boost::shared_ptr<T> >
        : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
      {
        bool operator()(const boost::shared_ptr<T>& a,
            const boost::shared_ptr<T>& b) const
          { return less<T*>()(a.get(),b.get()); }
      };

    } // namespace std

Specialization of std::swap uses the fast, non-throwing swap that's provided as a member function instead of using the default algorithm which creates a temporary and uses assignment.
Specialization of std::less allows use of shared pointers as keys in C++ Standard Library associative collections.
The std::less specializations use std::less<T*> to perform the comparison. This insures that pointers are handled correctly, since the standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] paragraph 8).
It's still a controversial question whether supplying only std::less is better than supplying a full range of comparison operators (<, >, <=, >=).

The current implementation does not supply the specializations if the macro name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

The current implementation does not supply the member template functions if the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

## Class shared_ptr Members

### shared_ptr element_type

    typedef T element_type;

Provides the type of the stored pointer.

### shared_ptr constructors

    explicit shared_ptr( T* p=0 );

Constructs a shared_ptr, storing a copy of `p`, which must have been allocated via a C++ `new` expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_ptr).

The only exception which may be thrown by this constructor is `std::bad_alloc`. If an exception is thrown, `delete p` is called.

    shared_ptr( const shared_ptr& r);  // never throws
    template<typename Y>
       shared_ptr(const shared_ptr<Y>& r);  // never throws
    template<typename Y>
       shared_ptr(std::auto_ptr<Y>& r);

Constructs a shared_ptr, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count(), or 1 in the auto_ptr case. In the auto_ptr case, r.release() is called.

The only exception which may be thrown by the constructor from auto_ptr is `std::bad_alloc`. If an exception is thrown, that constructor has no effect.

### shared_ptr destructor

    ~shared_ptr();

If use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ `delete` on a pointer with a value of 0 is harmless.

Does not throw exceptions.

### shared_ptr operator=

    shared_ptr& operator=( const shared_ptr& r);
    template<typename Y>
       shared_ptr& operator=(const shared_ptr<Y>& r);
    template<typename Y>
       shared_ptr& operator=(std::auto_ptr<Y>& r);

First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1. Note that in C++ `delete` on a pointer with a value of 0 is harmless.

Then replaces the contents of this, as if by storing a copy of the pointer stored in r. Afterwards, use_count() for all copies is 1 more than the initial r.use_count(), or 1 in the auto_ptr case. In the auto_ptr case, r.release() is called.

The first two forms of `operator=` above do not throw exceptions.

The only exception which may be thrown by the auto_ptr form is `std::bad_alloc`. If an exception is thrown, the function has no effect.

### shared_ptr reset

    void reset( T* p=0 );

First, if use_count() == 1, deletes the object pointed to by the stored pointer. Otherwise, use_count() for any remaining copies is decremented by 1.

Then replaces the contents of this, as if by storing a copy of p, which must have been allocated via a C++ `new` expression or be 0. Afterwards, use_count() is 1 (even if p==0; see ~shared_ptr). Note that in C++ `delete` on a pointer with a value of 0 is harmless.

The only exception which may be thrown is `std::bad_alloc`. If an exception is thrown, `delete p` is called.

### shared_ptr operator*

    T& operator*() const;  // never throws

Returns a reference to the object pointed to by the stored pointer.

### shared_ptr operator-> and get

    T* operator->() const;  // never throws
    T* get() const;  // never throws

T is not required by get() to be a complete type . See Common Requirements.

Both return the stored pointer.

### shared_ptr use_count

`long use_count() const; // never throws`

T is not required be a complete type. See Common Requirements.

Returns the number of shared_ptrs sharing ownership of the stored pointer.

### shared_ptr unique

`bool unique() const; // never throws`

T is not required be a complete type. See Common Requirements.

Returns use_count() == 1.

### shared_ptr swap

`void swap( shared_ptr<T>& other ) throw()`

T is not required be a complete type. See Common Requirements.

Swaps the two smart pointers, as if by std::swap.

## Class shared_ptr example

See shared_ptr_example.cpp for a complete example program.

This program builds a std::vector and std::set of FooPtr's.

Note that after the two containers have been populated, some of the FooPtr objects will have use_count()==1 rather than use_count()==2, since foo_set is a std::set rather than a std::multiset, and thus does not contain duplicate entries. Furthermore, use_count() may be even higher at various times while push_back() and insert() container operations are performed. More complicated yet, the container operations may throw exceptions under a variety of circumstances. Without using a smart pointer, memory and exception management would be a nightmare.

## Handle/Body Idiom

One common usage of shared_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.

The shared_ptr_example2_test.cpp sample program includes a header file, shared_ptr_example2.hpp, which uses a shared_ptr<> to an incomplete type to hide the implementation. The instantiation of member functions which require a complete type occurs in the shared_ptr_example2.cpp implementation file.

## Frequently Asked Questions

Q. Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?
A. Parameterization discourages users. Shared_ptr is carefully crafted to meet common needs without extensive parameterization. Someday a highly configurable smart pointer may be invented that is also very easy to use and very hard to misuse. Until then, shared_ptr is the smart pointer of choice for a wide range of applications. (Those interested in policy based smart pointers should read Modern C++ Design by Andrei Alexandrescu.)

Q. Why doesn't shared_ptr use a linked list implementation?
A. A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. See timings page.

Q. Why don't shared_ptr (and the other Boost smart pointers) supply an automatic conversion to T*?
A. Automatic conversion is believed to be too error prone.

Q. Why does shared_ptr supply use_count()?
A. As an aid to writing test cases and debugging displays. One of the progenitors had use_count(), and it was useful in tracking down bugs in a complex project that turned out to have cyclic-dependencies.

Q. Why doesn't shared_ptr specify complexity requirements?
A. Because complexity limit implementors and complicate the specification without apparent benefit to shared_ptr users. For example, error-checking implementations might become non-conforming if they had to meet stringent complexity requirements.

Q. Why doesn't shared_ptr provide (your pet feature here)?
A. Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent. [Provided by Peter Dimov]

Revised 13 July, 2001

© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.