std::shared_ptr - cppreference.com

##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# std::shared_ptr

From cppreference.com
< cpp‎ | memory

Defined in header `<memory>` |  |
template< class T > class shared_ptr; |  | (since C++11)

`std::shared_ptr` is a smart pointer that retains shared ownership of an object through a pointer. Several `shared_ptr` objects may own the same object. The object is destroyed and its memory deallocated when either of the following happens:

- the last remaining `shared_ptr` owning the object is destroyed.

- the last remaining `shared_ptr` owning the object is assigned another pointer via operator= or reset().

The object is destroyed using `delete-expression` or a custom deleter that is supplied to `shared_ptr` during construction.

A `shared_ptr` can share ownership of an object while storing a pointer to another object. This feature can be used to point to member objects while owning the object they belong to. The stored pointer is the one accessed by get(), the dereference and the comparison operators. The managed pointer is the one passed to the deleter when use count reaches zero.

A `shared_ptr` may also own no objects, in which case it is called empty (an empty shared_ptr may have a non-null stored pointer if the aliasing constructor was used to create it)

All specializations of `shared_ptr` meet the requirements of `CopyConstructible`, `CopyAssignable`, and `LessThanComparable` and are contextually convertible to `bool`.

All member functions (including copy constructor and copy assignment) can be called by multiple threads on different instances of `shared_ptr` without additional synchronization even if these instances are copies and share ownership of the same object. If multiple threads of execution access the same `shared_ptr` without synchronization and any of those accesses uses a non-const member function of `shared_ptr` then a data race will occur; the shared_ptr overloads of atomic functions can be used to prevent the data race.

### [edit] Member types

Member type | Definition
element_type | T

### [edit] Member functions

(constructor) | constructs new `shared_ptr` (public member function) [edit]
(destructor) | destructs the owned object if no more `shared_ptr`s link to it (public member function) [edit]
operator= | assigns the `shared_ptr` (public member function) [edit]
##### Modifiers
reset | replaces the managed object (public member function) [edit]
swap | swaps the managed objects (public member function) [edit]
##### Observers
get | returns a pointer to the managed object (public member function) [edit]
operator*operator-> | dereferences pointer to the managed object (public member function) [edit]
use_count | returns the number of `shared_ptr` objects referring to the same managed object (public member function) [edit]
unique | checks whether the managed object is managed only by the current `shared_ptr` instance (public member function) [edit]
operator bool | checks if there is associated managed object (public member function) [edit]
owner_before | provides owner-based ordering of shared pointers (public member function) [edit]

### [edit] Non-member functions

make_shared | creates a shared pointer that manages a new object (function template) [edit]
allocate_shared | creates a shared pointer that manages a new object allocated using an allocator (function template) [edit]
static_pointer_castdynamic_pointer_castconst_pointer_cast | applies `static_cast`, `dynamic_cast` or `const_cast` to the type of the managed object (function template) [edit]
get_deleter | returns the deleter of specified type, if owned (function template) [edit]
operator==operator!=operator<operator<=operator>operator>= | compares with another `shared_ptr` or with nullptr (function template) [edit]
operator<< | outputs the value of the managed pointer to an output stream (function template) [edit]
std::swap(std::shared_ptr) (C++11) | specializes the std::swap algorithm (function template) [edit]

std::atomic_is_lock_free(std::shared_ptr)std::atomic_load(std::shared_ptr)std::atomic_load_explicit(std::shared_ptr)std::atomic_store(std::shared_ptr)std::atomic_store_explicit(std::shared_ptr)std::atomic_exchange(std::shared_ptr)std::atomic_exchange_explicit(std::shared_ptr)std::atomic_compare_exchange_weak(std::shared_ptr)std::atomic_compare_exchange_strong(std::shared_ptr)std::atomic_compare_exchange_weak_explicit(std::shared_ptr)std::atomic_compare_exchange_strong_explicit(std::shared_ptr) | specializes atomic operations (function template) [edit]

### [edit] Helper classes

std::hash<std::shared_ptr> (C++11) | hash support for std::shared_ptr (class template specialization) [edit]

### [edit] Notes

The ownership of an object can only be shared with another `shared_ptr` by copy constructing or copy assigning its value to another `shared_ptr`. Constructing a new `shared_ptr` using the raw underlying pointer owned by another `shared_ptr` leads to undefined behavior.

`std::shared_ptr` may be used with an incomplete type `T`, but `T` must be complete at the point in code where the constructor from a raw pointer or the `reset(T*)` member function is called (note that std::unique_ptr may be constructed from a raw pointer to an incomplete type).

### [edit] Implementation notes

In a typical implementation, std::shared_ptr holds only two pointers:

- the stored pointer (one returned by get())
- a pointer to control block

The control block is a dynamically-allocated object that holds:

- either a pointer to the managed object or the managed object itself
- the deleter (type-erased)
- the allocator (type-erased)
- the number of `shared_ptr`s that own the managed object
- the number of `weak_ptr`s that refer to the managed object

When `shared_ptr` is created by calling std::make_shared or std::allocate_shared, the memory for both the control block and the managed object is created with a single allocation. The managed object is constructed in-place in a data member of the control block. When `shared_ptr` is created via one of the `shared_ptr` constructors, the managed object and the control block must be allocated separately. In this case, the control block stores a pointer to the managed object.

The pointer held by the `shared_ptr` directly is the one returned by get(), while the pointer/object held by the control block is the one that will be deleted when the number of shared owners reaches zero. These pointers are not necessarily equal.

The destructor of `shared_ptr` decrements the number of shared owners of the control block. If that counter reaches zero, the control block calls the destructor of the managed object. The control block does not deallocate itself until the std::weak_ptr counter reaches zero as well.

In practical implementations, the number of weak pointers may be incremented if there is a shared pointer to the same control block.

To satisfy thread safety requirements, the reference counters are typically incremented and decremented using an equivalent of std::atomic::fetch_add with std::memory_order_relaxed.

### [edit] Example

Run this code

    #include <iostream>
    #include <memory>
    #include <thread>
    #include <chrono>
    #include <mutex>

    struct Base
    {
        Base() { std::cout << "  Base::Base()\n"; }
        // Note: non-virtual destructor is OK here
        ~Base() { std::cout << "  Base::~Base()\n"; }
    };
    struct Derived: public Base
    {
        Derived() { std::cout << "  Derived::Derived()\n"; }
        ~Derived() { std::cout << "  Derived::~Derived()\n"; }
    };

    void thr(std::shared_ptr<Base> p)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::shared_ptr<Base> lp = p; // thread-safe, even though the
                                      // shared use_count is incremented
        {
          static std::mutex io_mutex;
          std::lock_guard<std::mutex> lk(io_mutex);
          std::cout << "local pointer in a thread:\n"
                    << "  lp.get() = " << lp.get()
                    << ", lp.use_count() = " << lp.use_count() << '\n';
        }
    }

    int main()
    {
        std::shared_ptr<Base> p = std::make_shared<Derived>();

        std::cout << "Created a shared Derived (as a pointer to Base)\n"
                  << "  p.get() = " << p.get()
                  << ", p.use_count() = " << p.use_count() << '\n';
        std::thread t1(thr, p), t2(thr, p), t3(thr, p);
        p.reset(); // release ownership from main
        std::cout << "Shared ownership between 3 threads and released\n"
                  << "ownership from main:\n"
                  << "  p.get() = " << p.get()
                  << ", p.use_count() = " << p.use_count() << '\n';
        t1.join(); t2.join(); t3.join();
        std::cout << "All threads completed, the last one deleted Derived\n";
    }

Possible output:

    Base::Base()
      Derived::Derived()
    Created a shared Derived (as a pointer to Base)
      p.get() = 0xc99028, p.use_count() = 1
    Shared ownership between 3 threads and released
    ownership from main:
      p.get() = (nil), p.use_count() = 0
    local pointer in a thread:
      lp.get() = 0xc99028, lp.use_count() = 3
    local pointer in a thread:
      lp.get() = 0xc99028, lp.use_count() = 4
    local pointer in a thread:
      lp.get() = 0xc99028, lp.use_count() = 2
      Derived::~Derived()
      Base::~Base()
    All threads completed, the last one deleted Derived

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/memory/shared_ptr&oldid=79771"