From a6323354cd808ed37f310ac50c5188c7e1e15424 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Mon, 2 Sep 2019 21:58:29 -0400 Subject: [PATCH] Update constraints and synopsis in documentation --- doc/smart_ptr.html | 10918 +++++++++++++++++++++++++ doc/smart_ptr/allocate_unique.adoc | 22 +- doc/smart_ptr/make_local_shared.adoc | 14 +- doc/smart_ptr/make_shared.adoc | 58 +- doc/smart_ptr/make_unique.adoc | 33 +- 5 files changed, 10975 insertions(+), 70 deletions(-) create mode 100644 doc/smart_ptr.html diff --git a/doc/smart_ptr.html b/doc/smart_ptr.html new file mode 100644 index 0000000..8647719 --- /dev/null +++ b/doc/smart_ptr.html @@ -0,0 +1,10918 @@ + + + + + + + + +Boost.SmartPtr: The Smart Pointer Library + + + + + +
+
+

Introduction

+
+
+

Smart pointers are objects which store pointers to dynamically allocated (heap) objects. +They behave much like built-in C++ pointers except that they automatically delete the object +pointed to at the appropriate time. Smart pointers are particularly useful in the face of +exceptions as they ensure proper destruction of dynamically allocated objects. They can also be +used to keep track of dynamically allocated objects shared by multiple owners.

+
+
+

Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for +deletion of the object when it is no longer needed. As such, they are examples of the "resource +acquisition is initialization" idiom described in Bjarne Stroustrup’s "The C++ Programming Language", +3rd edition, Section 14.4, Resource Management.

+
+
+

This library provides six smart pointer class templates:

+
+
+
    +
  • +

    scoped_ptr, used to contain ownership of a dynamically allocated object to the current scope;

    +
  • +
  • +

    scoped_array, which provides scoped ownership for a dynamically allocated array;

    +
  • +
  • +

    shared_ptr, a versatile tool for managing shared ownership of an object or array;

    +
  • +
  • +

    weak_ptr, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr;

    +
  • +
  • +

    intrusive_ptr, a pointer to objects with an embedded reference count;

    +
  • +
  • +

    local_shared_ptr, providing shared ownership within a single thread.

    +
  • +
+
+
+

shared_ptr and weak_ptr are part of the C++ standard since its 2011 iteration.

+
+
+

In addition, the library contains the following supporting utility functions and classes:

+
+
+
    +
  • +

    make_shared, a factory function for creating objects that returns a shared_ptr;

    +
  • +
  • +

    make_unique, a factory function returning std::unique_ptr;

    +
  • +
  • +

    allocate_unique, a factory function for creating objects using an allocator that returns a std::unique_ptr;

    +
  • +
  • +

    enable_shared_from_this, a helper base class that enables the acquisition of a shared_ptr pointing to this;

    +
  • +
  • +

    pointer_to_other, a helper trait for converting one smart pointer type to another;

    +
  • +
  • +

    static_pointer_cast and companions, generic smart pointer casts;

    +
  • +
  • +

    intrusive_ref_counter, a helper base class containing a reference count.

    +
  • +
  • +

    atomic_shared_ptr, a helper class implementing the interface of std::atomic for a value of type shared_ptr.

    +
  • +
+
+
+

As a general rule, the destructor or operator delete for an object managed by pointers in the library +are not allowed to throw exceptions.

+
+
+
+
+

Revision History

+
+
+

Changes in 1.72.0

+
+
    +
  • +

    Added allocate_unique

    +
  • +
+
+
+
+

Changes in 1.71.0

+
+
    +
  • +

    Added aliasing constructors to weak_ptr

    +
  • +
  • +

    Added weak_ptr<T>::empty()

    +
  • +
  • +

    Added enable_shared_from, shared_from, and weak_from

    +
  • +
+
+
+
+

Changes in 1.65.0

+
+
    +
  • +

    Added atomic_shared_ptr

    +
  • +
  • +

    Added local_shared_ptr, make_local_shared

    +
  • +
+
+
+
+
+
+

scoped_ptr: Scoped Object Ownership

+
+
+

Description

+
+

The scoped_ptr class template 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, either on destruction of the scoped_ptr, +or via an explicit reset. See the example.

+
+
+

scoped_ptr is a simple solution for simple needs. It supplies a basic "resource acquisition +is initialization" facility, without shared-ownership or transfer-of-ownership semantics. +Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain +ownership solely within the current scope. Because it is noncopyable, it is safer than shared_ptr +for pointers which should not be copied.

+
+
+

Because scoped_ptr is simple, in its usual implementation every operation is as fast as for a +built-in pointer and it has no more space overhead that a built-in pointer.

+
+
+

scoped_ptr cannot be used in C++ Standard Library containers. Use shared_ptr or std::unique_ptr +if you need a smart pointer that can.

+
+
+

scoped_ptr cannot correctly hold a pointer to a dynamically allocated array. See scoped_array for that usage.

+
+
+

The class template is parameterized on T, the type of the object pointed to. Destroying T must not thow exceptions, +and T must be complete at the point scoped_ptr<T>::~scoped_ptr is instantiated.

+
+
+
+

Synopsis

+
+

scoped_ptr is defined in <boost/smart_ptr/scoped_ptr.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class scoped_ptr {
+  private:
+
+    scoped_ptr(scoped_ptr const&);
+    scoped_ptr& operator=(scoped_ptr const&);
+
+    void operator==(scoped_ptr const&) const;
+    void operator!=(scoped_ptr const&) const;
+
+  public:
+
+    typedef T element_type;
+
+    explicit scoped_ptr(T * p = 0) noexcept;
+    ~scoped_ptr() noexcept;
+
+    void reset(T * p = 0) noexcept;
+
+    T & operator*() const noexcept;
+    T * operator->() const noexcept;
+    T * get() const noexcept;
+
+    explicit operator bool() const noexcept;
+
+    void swap(scoped_ptr & b) noexcept;
+  };
+
+  template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
+
+  template<class T>
+    bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+
+  template<class T>
+    bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef T element_type;
+
+
+
+

Provides the type of the stored pointer.

+
+
+
+

constructor

+
+
+
explicit scoped_ptr(T * p = 0) noexcept;
+
+
+
+

Constructs a scoped_ptr, storing a copy of p, which must have been allocated via a +C++ new expression or be 0. T is not required be a complete type.

+
+
+
+

destructor

+
+
+
~scoped_ptr() noexcept;
+
+
+
+

Destroys the object pointed to by the stored pointer, if any, as if by using +delete this->get(). T must be a complete type.

+
+
+
+

reset

+
+
+
void reset(T * p = 0) noexcept;
+
+
+
+

Deletes the object pointed to by the stored pointer and then stores a copy of +p, which must have been allocated via a C++ new expression or be 0.

+
+
+

Since the previous object needs to be deleted, T must be a complete type.

+
+
+
+

indirection

+
+
+
T & operator*() const noexcept;
+
+
+
+

Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0.

+
+
+
+
T * operator->() const noexcept;
+
+
+
+

Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

+
+
+
+

get

+
+
+
T * get() const noexcept;
+
+
+
+

Returns the stored pointer. T need not be a complete type.

+
+
+
+

conversions

+
+
+
explicit operator bool () const noexcept; // never throws
+
+
+
+

Returns get() != 0.

+
+
+ + + + + +
+
Note
+
+On C++03 compilers, the return value is of an unspecified type. +
+
+
+
+

swap

+
+
+
void swap(scoped_ptr & b) noexcept;
+
+
+
+

Exchanges the contents of the two smart pointers. T need not be a complete type.

+
+
+
+
+

Free Functions

+
+

swap

+
+
+
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
+
+
+
+

Equivalent to a.swap(b).

+
+
+
+

comparisons

+
+
+
template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+
+
+
+
+
template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+
+
+
+

Returns p.get() == nullptr.

+
+
+
+
template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
+
+
+
+
+
template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
+
+
+
+

Returns p.get() != nullptr.

+
+
+
+
+

Example

+
+

Here’s an example that uses scoped_ptr.

+
+
+
+
#include <boost/scoped_ptr.hpp>
+#include <iostream>
+
+struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
+
+class MyClass {
+    boost::scoped_ptr<int> ptr;
+  public:
+    MyClass() : ptr(new int) { *ptr = 0; }
+    int add_one() { return ++*ptr; }
+};
+
+int main()
+{
+    boost::scoped_ptr<Shoe> x(new Shoe);
+    MyClass my_instance;
+    std::cout << my_instance.add_one() << '\n';
+    std::cout << my_instance.add_one() << '\n';
+}
+
+
+
+

The example program produces the beginning of a child’s nursery rhyme:

+
+
+
+
1
+2
+Buckle my shoe
+
+
+
+
+

Rationale

+
+

The primary reason to use scoped_ptr rather than std::auto_ptr or std::unique_ptr is to let readers of your code +know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership.

+
+
+

A secondary reason to use scoped_ptr is to prevent a later maintenance programmer from adding a function that transfers +ownership by returning the auto_ptr, because the maintenance programmer saw auto_ptr, and assumed ownership could safely be transferred.

+
+
+

Think of bool vs int. We all know that under the covers bool is usually just an int. Indeed, some argued against including bool in the C++ +standard because of that. But by coding bool rather than int, you tell your readers what your intent is. Same with scoped_ptr; by using it you are signaling intent.

+
+
+

It has been suggested that scoped_ptr<T> is equivalent to std::auto_ptr<T> const. Ed Brey pointed out, however, that reset will not work on a std::auto_ptr<T> const.

+
+
+
+

Handle/Body Idiom

+
+

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

+
+
+

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

+
+
+
+

Frequently Asked Questions

+
+
    +
  1. +

    Why doesn’t scoped_ptr have a release() member?

    +

    When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If scoped_ptr had a release() member, +it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use std::auto_ptr where +transfer of ownership is required. (supplied by Dave Abrahams)

    +
  2. +
+
+
+
+
+
+

scoped_array: Scoped Array Ownership

+
+
+

Description

+
+

The scoped_array class template stores a pointer to a dynamically allocated array. +(Dynamically allocated arrays are allocated with the C++ new[] expression.) The array +pointed to is guaranteed to be deleted, either on destruction of the scoped_array, +or via an explicit reset.

+
+
+

The scoped_array template is a simple solution for simple needs. It supplies a basic +"resource acquisition is initialization" facility, without shared-ownership or +transfer-of-ownership semantics. Both its name and enforcement of semantics +(by being noncopyable) signal its intent to retain ownership solely within the current scope. +Because it is noncopyable, it is safer than shared_ptr<T[]> for pointers which should not be copied.

+
+
+

Because scoped_array is so simple, in its usual implementation every operation is as fast as a +built-in array pointer and it has no more space overhead that a built-in array pointer.

+
+
+

It cannot be used in C++ standard library containers. See shared_ptr<T[]> if scoped_array +does not meet your needs.

+
+
+

It cannot correctly hold a pointer to a single object. See scoped_ptr for that usage.

+
+
+

std::vector is an alternative to scoped_array that is a bit heavier duty but far more flexible. +boost::array is an alternative that does not use dynamic allocation.

+
+
+

The class template is parameterized on T, the type of the object pointed to.

+
+
+
+

Synopsis

+
+

scoped_array is defined in <boost/smart_ptr/scoped_array.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class scoped_array {
+  private:
+
+    scoped_array(scoped_array const &);
+    scoped_array & operator=(scoped_array const &);
+
+    void operator==( scoped_array const& ) const;
+    void operator!=( scoped_array const& ) const;
+
+  public:
+
+    typedef T element_type;
+
+    explicit scoped_array(T * p = 0) noexcept;
+    ~scoped_array() noexcept;
+
+    void reset(T * p = 0) noexcept;
+
+    T & operator[](std::ptrdiff_t i) const noexcept;
+    T * get() const noexcept;
+
+    explicit operator bool () const noexcept;
+
+    void swap(scoped_array & b) noexcept;
+  };
+
+  template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
+
+  template<class T>
+    bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+
+  template<class T>
+    bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+  template<class T>
+    bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef T element_type;
+
+
+
+

Provides the type of the stored pointer.

+
+
+
+

constructors

+
+
+
explicit scoped_array(T * p = 0) noexcept;
+
+
+
+

Constructs a scoped_array, storing a copy of p, which must have been +allocated via a C++ new[] expression or be 0. T is not required be a complete type.

+
+
+
+

destructor

+
+
+
~scoped_array() noexcept;
+
+
+
+

Deletes the array pointed to by the stored pointer. Note that delete[] on a pointer with +a value of 0 is harmless. T must be complete, and delete[] on the stored pointer must +not throw exceptions.

+
+
+
+

reset

+
+
+
void reset(T * p = 0) noexcept;
+
+
+
+

Deletes the array pointed to by the stored pointer and then stores a copy of p, +which must have been allocated via a C++ new[] expression or be 0. T must be complete, +and delete[] on the stored pointer must not throw exceptions.

+
+
+
+

subscripting

+
+
+
T & operator[](std::ptrdiff_t i) const noexcept;
+
+
+
+

Returns a reference to element i of the array pointed to by the stored pointer. +Behavior is undefined and almost certainly undesirable if the stored pointer is 0, +or if i is less than 0 or is greater than or equal to the number of elements in +the array.

+
+
+
+

get

+
+
+
T * get() const noexcept;
+
+
+
+

Returns the stored pointer. T need not be a complete type.

+
+
+
+

conversions

+
+
+
explicit operator bool () const noexcept;
+
+
+
+

Returns get() != 0.

+
+
+ + + + + +
+
Note
+
+On C++03 compilers, the return value is of an unspecified type. +
+
+
+
+

swap

+
+
+
void swap(scoped_array & b) noexcept;
+
+
+
+

Exchanges the contents of the two smart pointers. T need not be a complete type.

+
+
+
+
+

Free Functions

+
+

swap

+
+
+
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
+
+
+
+

Equivalent to a.swap(b).

+
+
+
+

comparisons

+
+
+
template<class T>
+  bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+
+
+
+
+
template<class T>
+  bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+
+
+
+

Returns p.get() == nullptr.

+
+
+
+
template<class T>
+  bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
+
+
+
+
+
template<class T>
+  bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
+
+
+
+

Returns p.get() != nullptr.

+
+
+
+
+
+
+

shared_ptr: Shared Ownership

+
+
+

Description

+
+

The shared_ptr class template stores a pointer to a dynamically allocated object, typically with a C++ new-expression. +The object pointed to is guaranteed to be deleted when the last shared_ptr pointing to it is destroyed or reset.

+
+
+
Code Example 1. Using shared_ptr
+
+
shared_ptr<X> p1( new X );
+shared_ptr<void> p2( new int(5) );
+
+
+
+

shared_ptr deletes the exact pointer that has been passed at construction time, complete with its original type, regardless +of the template parameter. In the second example above, when p2 is destroyed or reset, it will call delete on the original +int* that has been passed to the constructor, even though p2 itself is of type shared_ptr<void> and stores a pointer of +type void*.

+
+
+

Every shared_ptr meets the CopyConstructible, MoveConstructible, CopyAssignable and MoveAssignable requirements of the +C++ Standard Library, and can be used in standard library containers. Comparison operators are supplied so that shared_ptr +works with the standard library’s associative containers.

+
+
+

Because the implementation uses reference counting, cycles of shared_ptr instances will not be reclaimed. For example, if main() +holds a shared_ptr to A, which directly or indirectly holds a shared_ptr back to A, A’s use count will be 2. Destruction +of the original `shared_ptr will leave A dangling with a use count of 1. Use weak_ptr to "break cycles."

+
+
+

The class template is parameterized on T, the type of the object pointed to. shared_ptr and most of its member functions place +no requirements on T; it is allowed to be an incomplete type, or void. Member functions that do place additional requirements +(constructors, reset) are explicitly documented below.

+
+
+

shared_ptr<T> can be implicitly converted to shared_ptr<U> whenever T* can be implicitly converted to U*. In particular, +shared_ptr<T> is implicitly convertible to shared_ptr<T const>, to shared_ptr<U> where U is an accessible base of T, +and to shared_ptr<void>.

+
+
+

shared_ptr is now part of the C++11 Standard, as std::shared_ptr.

+
+
+

Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically allocated array. This is accomplished +by using an array type (T[] or T[N]) as the template parameter. There is almost no difference between using an unsized array, +T[], and a sized array, T[N]; the latter just enables operator[] to perform a range check on the index.

+
+
+
Code Example 2. Using shared_ptr with arrays
+
+
shared_ptr<double[1024]> p1( new double[1024] );
+shared_ptr<double[]> p2( new double[n] );
+
+
+
+
+

Best Practices

+
+

A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result +of new. Every occurence of the new keyword in the code should have the form:

+
+
+
+
shared_ptr<T> p(new Y);
+
+
+
+

It is, of course, acceptable to use another smart pointer in place of shared_ptr above; having T and Y be the same type, or passing +arguments to the constructor of Y is also OK.

+
+
+

If you observe this guideline, it naturally follows that you will have no explicit delete statements; try/catch constructs will be rare.

+
+
+

Avoid using unnamed shared_ptr temporaries to save typing; to see why this is dangerous, consider this example:

+
+
+
Code Example 3. Exception-safe and -unsafe use of shared_ptr
+
+
void f(shared_ptr<int>, int);
+int g();
+
+void ok()
+{
+    shared_ptr<int> p( new int(2) );
+    f( p, g() );
+}
+
+void bad()
+{
+    f( shared_ptr<int>( new int(2) ), g() );
+}
+
+
+
+

The function ok follows the guideline to the letter, whereas bad constructs the temporary shared_ptr in place, admitting the possibility of +a memory leak. Since function arguments are evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, +and we may never get to the shared_ptr constructor if g throws an exception. See Herb Sutter’s treatment of +the issue for more information.

+
+
+

The exception safety problem described above may also be eliminated by using the make_shared or allocate_shared factory +functions defined in <boost/smart_ptr/make_shared.hpp>. These factory functions also provide an efficiency benefit by consolidating allocations.

+
+
+
+

Synopsis

+
+

shared_ptr is defined in <boost/smart_ptr/shared_ptr.hpp>.

+
+
+
+
namespace boost {
+
+  class bad_weak_ptr: public std::exception;
+
+  template<class T> class weak_ptr;
+
+  template<class T> class shared_ptr {
+  public:
+
+    typedef /*see below*/ element_type;
+
+    constexpr shared_ptr() noexcept;
+    constexpr shared_ptr(std::nullptr_t) noexcept;
+
+    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 D> shared_ptr(std::nullptr_t p, D d);
+    template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
+
+    ~shared_ptr() noexcept;
+
+    shared_ptr(shared_ptr const & r) noexcept;
+    template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept;
+
+    shared_ptr(shared_ptr && r) noexcept;
+    template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;
+
+    template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;
+
+    template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
+
+    template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
+    template<class Y> shared_ptr(std::auto_ptr<Y> && r);
+
+    template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
+
+    shared_ptr & operator=(shared_ptr const & r) noexcept;
+    template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+
+    shared_ptr & operator=(shared_ptr const && r) noexcept;
+    template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r) noexcept;
+
+    template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
+    template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
+
+    template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
+
+    shared_ptr & operator=(std::nullptr_t) noexcept;
+
+    void reset() noexcept;
+
+    template<class Y> void reset(Y * p);
+    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, element_type * p) noexcept;
+    template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;
+
+    T & operator*() const noexcept; // only valid when T is not an array type
+    T * operator->() const noexcept; // only valid when T is not an array type
+
+    // only valid when T is an array type
+    element_type & operator[](std::ptrdiff_t i) const noexcept;
+
+    element_type * get() const noexcept;
+
+    bool unique() const noexcept;
+    long use_count() const noexcept;
+
+    explicit operator bool() const noexcept;
+
+    void swap(shared_ptr & b) noexcept;
+
+    template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
+    template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
+  };
+
+  template<class T, class U>
+    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+  template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+
+  template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+
+  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
+
+  template<class T>
+    typename shared_ptr<T>::element_type *
+      get_pointer(shared_ptr<T> const & p) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+  template<class E, class T, class Y>
+    std::basic_ostream<E, T> &
+      operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
+
+  template<class D, class T> D * get_deleter(shared_ptr<T> const & p) noexcept;
+
+  template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;
+
+  template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;
+  template<class T>
+    shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;
+
+  template<class T>
+    void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+  template<class T>
+    void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+
+  template<class T>
+    shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+  template<class T>
+    shared_ptr<T> atomic_exchange_explicit(
+      shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+
+  template<class T>
+    bool atomic_compare_exchange(
+      shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;
+  template<class T>
+    bool atomic_compare_exchange_explicit(
+      shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef ... element_type;
+
+
+
+

element_type is T when T is not an array type, and U when T is U[] or U[N].

+
+
+
+

default constructor

+
+
+
constexpr shared_ptr() noexcept;
+
+
+
+
+
constexpr shared_ptr(std::nullptr_t) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs an empty shared_ptr.

    +
    +
    Postconditions
    +
    +

    use_count() == 0 && get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+

pointer constructor

+
+
+
template<class Y> explicit shared_ptr(Y * p);
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y must be a complete type. The expression delete[] p, when T is an array type, or delete p, when T is not an array type, +must be well-formed, well-defined, and not throw exceptions. When T is U[N], Y(*)[N] must be convertible to T*; when T is U[], Y(*)[] +must be convertible to T*; otherwise, Y* must be convertible to T*.

    +
    +
    Effects
    +
    +

    When T is not an array type, constructs a shared_ptr that owns the pointer p. Otherwise, constructs a shared_ptr that owns p and +a deleter of an unspecified type that calls delete[] p.

    +
    +
    Postconditions
    +
    +

    use_count() == 1 && get() == p. If T is not an array type and p is unambiguously convertible to enable_shared_from_this<V>* +for some V, p->shared_from_this() returns a copy of *this.

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    Exception safety
    +
    +

    If an exception is thrown, the constructor calls delete[] p, when T is an array type, or delete p, when T is not an array type.

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+p must be a pointer to an object that was allocated via a C++ new expression or be 0. The postcondition that use count is 1 holds even if p +is 0; invoking delete on a pointer that has a value of 0 is harmless. +
+
+
+ + + + + +
+
Note
+
+This constructor is a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete +with its original type, even when T does not have a virtual destructor, or is void. +
+
+
+
+

constructors taking a deleter

+
+
+
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 D> shared_ptr(std::nullptr_t p, D d);
+
+
+
+
+
template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    D must be CopyConstructible. The copy constructor and destructor of D must not throw. The expression d(p) must be well-formed, well-defined, +and not throw exceptions. A must be an Allocator, as described in section Allocator Requirements [allocator.requirements] of the C++ Standard. +When T is U[N], Y(*)[N] must be convertible to T*; when T is U[], Y(*)[] must be convertible to T*; otherwise, Y* must be convertible to T*.

    +
    +
    Effects
    +
    +

    Constructs a shared_ptr that owns the pointer p and the deleter d. The constructors taking an allocator a allocate memory using a copy of a.

    +
    +
    Postconditions
    +
    +

    use_count() == 1 && get() == p. If T is not an array type and p is unambiguously convertible to enable_shared_from_this<V>* for some V, +p->shared_from_this() returns a copy of *this.

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    Exception safety
    +
    +

    If an exception is thrown, d(p) is called.

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+When the the time comes to delete the object pointed to by p, the stored copy of d is invoked with the stored copy of p as an argument. +
+
+
+ + + + + +
+
Note
+
+Custom deallocators allow a factory function returning a shared_ptr to insulate the user from its memory allocation strategy. Since the deallocator +is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For example, +a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object, and other variations allow a shared_ptr to be used as a wrapper +for another smart pointer, easing interoperability. +
+
+
+ + + + + +
+
Note
+
+The requirement that the copy constructor of D does not throw comes from the pass by value. If the copy constructor throws, the pointer would leak. +
+
+
+
+

copy and converting constructors

+
+
+
shared_ptr(shared_ptr const & r) noexcept;
+
+
+
+
+
template<class Y> shared_ptr(shared_ptr<Y> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +

    If r is empty, constructs an empty shared_ptr; otherwise, constructs a shared_ptr that shares ownership with r.

    +
    +
    Postconditions
    +
    +

    get() == r.get() && use_count() == r.use_count().

    +
    +
    +
    +
  • +
+
+
+
+

move constructors

+
+
+
shared_ptr(shared_ptr && r) noexcept;
+
+
+
+
+
template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +

    Move-constructs a shared_ptr from r.

    +
    +
    Postconditions
    +
    +

    *this contains the old value of r. r is empty and r.get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+

aliasing constructor

+
+
+
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Copy-constructs a shared_ptr from r, while storing p instead.

    +
    +
    Postconditions
    +
    +

    get() == p && use_count() == r.use_count().

    +
    +
    +
    +
  • +
+
+
+
+

aliasing move constructor

+
+
+
template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Move-constructs a shared_ptr from r, while storing p instead.

    +
    +
    Postconditions
    +
    +

    get() == p and use_count() equals the old count of r. r is empty and r.get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+

weak_ptr constructor

+
+
+
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +

    Constructs a shared_ptr that shares ownership with r and stores a copy of the pointer stored in r.

    +
    +
    Postconditions
    +
    +

    use_count() == r.use_count().

    +
    +
    Throws
    +
    +

    bad_weak_ptr when r.use_count() == 0.

    +
    +
    Exception safety
    +
    +

    If an exception is thrown, the constructor has no effect.

    +
    +
    +
    +
  • +
+
+
+
+

auto_ptr constructors

+
+
+
template<class Y> shared_ptr(std::auto_ptr<Y> & r);
+
+
+
+
+
template<class Y> shared_ptr(std::auto_ptr<Y> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +

    Constructs a shared_ptr, as if by storing a copy of r.release().

    +
    +
    Postconditions
    +
    +

    use_count() == 1.

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    Exception safety
    +
    +

    If an exception is thrown, the constructor has no effect.

    +
    +
    +
    +
  • +
+
+
+
+

unique_ptr constructor

+
+
+
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +
    +
      +
    • +

      When r.get() == 0, equivalent to shared_ptr();

      +
    • +
    • +

      When D is not a reference type, equivalent to shared_ptr(r.release(), r.get_deleter());

      +
    • +
    • +

      Otherwise, equivalent to shared_ptr(r.release(), del), where del is a deleter that stores the reference rd returned +from r.get_deleter() and del(p) calls rd(p).

      +
    • +
    +
    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    Exception safety
    +
    +

    If an exception is thrown, the constructor has no effect.

    +
    +
    +
    +
  • +
+
+
+
+

destructor

+
+
+
~shared_ptr() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +
    +
      +
    • +

      If *this is empty, or shares ownership with another shared_ptr instance (use_count() > 1), there are no side effects.

      +
    • +
    • +

      Otherwise, if *this owns a pointer p and a deleter d, d(p) is called.

      +
    • +
    • +

      Otherwise, *this owns a pointer p, and delete p is called.

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+
+

assignment

+
+
+
shared_ptr & operator=(shared_ptr const & r) noexcept;
+
+
+
+
+
template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+
+
+
+
+
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(r).swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+The use count updates caused by the temporary object construction and destruction are not considered observable side effects, +and the implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. +
+
+
+ + + + + +
+
Note
+
+
+

In particular, in the example:

+
+
+
+
shared_ptr<int> p(new int);
+shared_ptr<void> q(p);
+p = p;
+q = p;
+
+
+
+

both assignments may be no-ops.

+
+
+
+
+
+
shared_ptr & operator=(shared_ptr && r) noexcept;
+
+
+
+
+
template<class Y> shared_ptr & operator=(shared_ptr<Y> && r) noexcept;
+
+
+
+
+
template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
+
+
+
+
+
template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(std::move(r)).swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+
shared_ptr & operator=(std::nullptr_t) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr().swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+

reset

+
+
+
void reset() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr().swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> void reset(Y * p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(p).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y, class D> void reset(Y * p, D d);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(p, d).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y, class D, class A> void reset(Y * p, D d, A a);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(p, d, a).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(r, p).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> void reset(shared_ptr<Y> && r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to shared_ptr(std::move(r), p).swap(*this).

    +
    +
    +
    +
    +

    # indirection

    +
    +
  • +
+
+
+
+
T & operator*() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T should not be an array type. The stored pointer must not be 0.

    +
    +
    Returns
    +
    +

    *get().

    +
    +
    +
    +
  • +
+
+
+
+
T * operator->() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T should not be an array type. The stored pointer must not be 0.

    +
    +
    Returns
    +
    +

    get().

    +
    +
    +
    +
  • +
+
+
+
+
element_type & operator[](std::ptrdiff_t i) const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T should be an array type. The stored pointer must not be 0. i >= 0. If T is U[N], i < N.

    +
    +
    Returns
    +
    +

    get()[i].

    +
    +
    +
    +
  • +
+
+
+
+

get

+
+
+
element_type * get() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The stored pointer.

    +
    +
    +
    +
    +

    # unique

    +
    +
  • +
+
+
+
+
bool unique() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    use_count() == 1.

    +
    +
    +
    +
    +

    # use_count

    +
    +
  • +
+
+
+
+
long use_count() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The number of shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.

    +
    +
    +
    +
    +

    # conversions

    +
    +
  • +
+
+
+
+
explicit operator bool() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    get() != 0.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +This conversion operator allows shared_ptr objects to be used in boolean contexts, like if(p && p->valid()) {}. +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+The conversion to bool is not merely syntactic sugar. It allows shared_ptr variables to be declared in conditions when using +dynamic_pointer_cast or weak_ptr::lock. +
+
+
+ + + + + +
+
Note
+
+On C++03 compilers, the return value is of an unspecified type. +
+
+
+
+

swap

+
+
+
void swap(shared_ptr & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Exchanges the contents of the two smart pointers.

    +
    +
    +
    +
    +

    # owner_before

    +
    +
  • +
+
+
+
+
template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const noexcept;
+
+
+
+
+
template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    See the description of operator<.

    +
    +
    +
    +
    +

    ## Free Functions

    +
    +
  • +
+
+
+
+

comparison

+
+
+
template<class T, class U>
+  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() == b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() != b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T> bool operator==(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+
+
+
+
+
template<class T> bool operator==(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T> bool operator!=(shared_ptr<T> const & p, std::nullptr_t) noexcept;
+
+
+
+
+
template<class T> bool operator!=(std::nullptr_t, shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get() != 0.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    An unspecified value such that

    +
    +
      +
    • +

      operator< is a strict weak ordering as described in section [lib.alg.sorting] of the C++ standard;

      +
    • +
    • +

      under the equivalence relation defined by operator<, !(a < b) && !(b < a), two shared_ptr instances +are equivalent if and only if they share ownership or are both empty.

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+Allows shared_ptr objects to be used as keys in associative containers. +
+
+
+ + + + + +
+
Note
+
+The rest of the comparison operators are omitted by design. +
+
+
+
+

swap

+
+
+
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to a.swap(b).

    +
    +
    +
    +
    +

    # get_pointer

    +
    +
  • +
+
+
+
+
template<class T>
+  typename shared_ptr<T>::element_type *
+    get_pointer(shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get().

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Provided as an aid to generic programming. Used by mem_fn. +
    +
    +
  • +
+
+
+
+

static_pointer_cast

+
+
+
template<class T, class U>
+  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression static_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +

    shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Caution
+
+The seemingly equivalent expression shared_ptr<T>(static_cast<T*>(r.get())) will eventually +result in undefined behavior, attempting to delete the same object twice. +
+
+
+
+

const_pointer_cast

+
+
+
template<class T, class U>
+  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression const_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +

    shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

    +
    +
    +
    +
  • +
+
+
+
+

dynamic_pointer_cast

+
+
+
template<class T, class U>
+    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression dynamic_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +
    +
      +
    • +

      When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, shared_ptr<T>(r, p);

      +
    • +
    • +

      Otherwise, shared_ptr<T>().

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+
+

reinterpret_pointer_cast

+
+
+
template<class T, class U>
+  shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression reinterpret_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +

    shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

    +
    +
    +
    +
  • +
+
+
+
+

operator<<

+
+
+
template<class E, class T, class Y>
+  std::basic_ostream<E, T> &
+    operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    os << p.get();.

    +
    +
    Returns
    +
    +

    os.

    +
    +
    +
    +
  • +
+
+
+
+

get_deleter

+
+
+
template<class D, class T>
+  D * get_deleter(shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    If *this owns a deleter d of type (cv-unqualified) D, returns &d; otherwise returns 0.

    +
    +
    +
    +
    +

    # Atomic Access

    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+The function in this section are atomic with respect to the first shared_ptr argument, + identified by *p. Concurrent access to the same shared_ptr instance is not a data race, if + done exclusively by the functions in this section. +
+
+
+
+
template<class T> bool atomic_is_lock_free( shared_ptr<T> const * p ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    false.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +This implementation is not lock-free. +
    +
    +
  • +
+
+
+
+
template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) noexcept;
+
+
+
+
+
template<class T> shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, int ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    *p.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The int argument is the memory_order, but this implementation does not use it, as it’s lock-based + and therefore always sequentially consistent. +
    +
    +
  • +
+
+
+
+
template<class T>
+  void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+
+
+
+
+
template<class T>
+  void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    p->swap(r).

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) noexcept;
+
+
+
+
+
template<class T>
+  shared_ptr<T> atomic_exchange_explicit(
+    shared_ptr<T> * p, shared_ptr<T> r, int ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    p->swap(r).

    +
    +
    Returns
    +
    +

    The old value of *p.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  bool atomic_compare_exchange(
+    shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) noexcept;
+
+
+
+
+
template<class T>
+  bool atomic_compare_exchange_explicit(
+    shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, int, int ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    If *p is equivalent to *v, assigns w to *p, otherwise assigns *p to *v.

    +
    +
    Returns
    +
    +

    true if *p was equivalent to *v, false otherwise.

    +
    +
    Remarks
    +
    +

    Two shared_ptr instances are equivalent if they store the same pointer value and share ownership.

    +
    +
    +
    +
  • +
+
+
+
+
+

Example

+
+

See shared_ptr_example.cpp for a complete example program. The program builds a +std::vector and std::set of shared_ptr objects.

+
+
+

Note that after the containers have been populated, some of the shared_ptr objects will have a use count of 1 rather than +a use count of 2, since the set is a std::set rather than a std::multiset, and thus does not contain duplicate entries. +Furthermore, the 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. Getting the memory management +and exception handling in this example right without a smart pointer 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. Note that there is no need for an explicit destructor. Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete type.

+
+
+
+

Thread Safety

+
+

shared_ptr objects offer the same level of thread safety as built-in types. A shared_ptr instance can be "read" (accessed using only const operations) +simultaneously by multiple threads. Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) +simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.)

+
+
+

Any other simultaneous accesses result in undefined behavior.

+
+
+

Examples:

+
+
+
+
shared_ptr<int> p(new int(42));
+
+
+
+
Code Example 4. Reading a shared_ptr from two threads
+
+
// thread A
+shared_ptr<int> p2(p); // reads p
+
+// thread B
+shared_ptr<int> p3(p); // OK, multiple reads are safe
+
+
+
+
Code Example 5. Writing different shared_ptr instances from two threads
+
+
// thread A
+p.reset(new int(1912)); // writes p
+
+// thread B
+p2.reset(); // OK, writes p2
+
+
+
+
Code Example 6. Reading and writing a shared_ptr from two threads
+
+
// thread A
+p = p3; // reads p3, writes p
+
+// thread B
+p3.reset(); // writes p3; undefined, simultaneous read/write
+
+
+
+
Code Example 7. Reading and destroying a shared_ptr from two threads
+
+
// thread A
+p3 = p2; // reads p2, writes p3
+
+// thread B
+// p2 goes out of scope: undefined, the destructor is considered a "write access"
+
+
+
+
Code Example 8. Writing a shared_ptr from two threads
+
+
// thread A
+p3.reset(new int(1));
+
+// thread B
+p3.reset(new int(2)); // undefined, multiple writes
+
+
+
+

Starting with Boost release 1.33.0, shared_ptr uses a lock-free implementation on most common platforms.

+
+
+

If your program is single-threaded and does not link to any libraries that might have used shared_ptr in its default configuration, +you can #define the macro BOOST_SP_DISABLE_THREADS on a project-wide basis to switch to ordinary non-atomic reference count updates.

+
+
+

(Defining BOOST_SP_DISABLE_THREADS in some, but not all, translation units is technically a violation of the One Definition Rule and +undefined behavior. Nevertheless, the implementation attempts to do its best to accommodate the request to use non-atomic updates in those +translation units. No guarantees, though.)

+
+
+

You can define the macro BOOST_SP_USE_PTHREADS to turn off the lock-free platform-specific implementation and fall back to the generic +pthread_mutex_t-based code.

+
+
+
+

Frequently Asked Questions

+
+
    +
  1. +

    There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single implementation? It would be useful to be able to experiment with each type so as to find the most suitable for the job at hand?

    +

    An important goal of shared_ptr is to provide a standard shared-ownership pointer. Having a single pointer type is important for stable +library interfaces, since different shared pointers typically cannot interoperate, i.e. a reference counted pointer (used by library A) +cannot share ownership with a linked pointer (used by library B.)

    +
  2. +
  3. +

    Why doesn’t shared_ptr have template parameters supplying traits or policies to allow extensive user customization?

    +

    Parameterization discourages users. The shared_ptr template is carefully crafted to meet common needs without extensive parameterization.

    +
  4. +
  5. +

    I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?

    +

    Template parameters affect the type. See the answer to the first question above.

    +
  6. +
  7. +

    Why doesn’t shared_ptr use a linked list implementation?

    +

    A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. In addition, it is expensive to +make a linked list implementation thread safe.

    +
  8. +
  9. +

    Why doesn’t shared_ptr (or any of the other Boost smart pointers) supply an automatic conversion to T*?

    +

    Automatic conversion is believed to be too error prone.

    +
  10. +
  11. +

    Why does shared_ptr supply use_count()?

    +

    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.

    +
  12. +
  13. +

    Why doesn’t shared_ptr specify complexity requirements?

    +

    Because complexity requirements 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.

    +
  14. +
  15. +

    Why doesn’t shared_ptr provide a release() function?

    +

    shared_ptr cannot give away ownership unless it’s unique() because the other copy will still destroy the object.

    +
    +

    Consider:

    +
    +
    +
    +
    shared_ptr<int> a(new int);
    +shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
    +
    +int * p = a.release();
    +
    +// Who owns p now? b will still call delete on it in its destructor.
    +
    +
    +
    +

    Furthermore, the pointer returned by release() would be difficult to deallocate reliably, as the source shared_ptr could have been created with a +custom deleter, or may have pointed to an object of a different type.

    +
    +
  16. +
  17. +

    Why is operator->() const, but its return value is a non-const pointer to the element type?

    +

    Shallow copy pointers, including raw pointers, typically don’t propagate constness. It makes little sense for them to do so, as you can always obtain a +non-const pointer from a const one and then proceed to modify the object through it. shared_ptr is "as close to raw pointers as possible but no closer".

    +
  18. +
+
+
+
+
+
+

weak_ptr: Non-owning Observer

+
+
+

Description

+
+

The weak_ptr class template stores a "weak reference" to an object that’s already managed by a shared_ptr. +To access the object, a weak_ptr can be converted to a shared_ptr using the shared_ptr constructor taking +weak_ptr, or the weak_ptr member function lock. When the last shared_ptr to the object goes away and the +object is deleted, the attempt to obtain a shared_ptr from the weak_ptr instances that refer to the deleted +object will fail: the constructor will throw an exception of type boost::bad_weak_ptr, and weak_ptr::lock will +return an empty shared_ptr.

+
+
+

Every weak_ptr meets the CopyConstructible and Assignable requirements of the C++ Standard Library, and so +can be used in standard library containers. Comparison operators are supplied so that weak_ptr works with the standard +library’s associative containers.

+
+
+

weak_ptr operations never throw exceptions.

+
+
+

The class template is parameterized on T, the type of the object pointed to.

+
+
+

Compared to shared_ptr, weak_ptr provides a very limited subset of operations since accessing its stored pointer is +often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined +behavior.) Pretend for a moment that weak_ptr had a get member function that returned a raw pointer, and consider this innocent +piece of code:

+
+
+
+
shared_ptr<int> p(new int(5));
+weak_ptr<int> q(p);
+
+// some time later
+
+if(int * r = q.get())
+{
+    // use *r
+}
+
+
+
+

Imagine that after the if, but immediately before r is used, another thread executes the statement p.reset(). Now r is a dangling pointer.

+
+
+

The solution to this problem is to create a temporary shared_ptr from q:

+
+
+
+
shared_ptr<int> p(new int(5));
+weak_ptr<int> q(p);
+
+// some time later
+
+if(shared_ptr<int> r = q.lock())
+{
+    // use *r
+}
+
+
+
+

Now r holds a reference to the object that was pointed by q. Even if p.reset() is executed in another thread, the object will stay alive until +r goes out of scope or is reset. By obtaining a shared_ptr to the object, we have effectively locked it against destruction.

+
+
+
+

Synopsis

+
+

weak_ptr is defined in <boost/smart_ptr/weak_ptr.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class weak_ptr {
+  public:
+
+    typedef /*see below*/ element_type;
+
+    weak_ptr() noexcept;
+
+    template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
+    weak_ptr(weak_ptr const & r) noexcept;
+    template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
+
+    weak_ptr(weak_ptr && r) noexcept;
+
+    template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
+
+    ~weak_ptr() noexcept;
+
+    weak_ptr & operator=(weak_ptr const & r) noexcept;
+    weak_ptr & operator=(weak_ptr && r) noexcept;
+    template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
+    template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+
+    long use_count() const noexcept;
+    bool expired() const noexcept;
+
+    bool empty() const noexcept;
+
+    shared_ptr<T> lock() const noexcept;
+
+    void reset() noexcept;
+
+    void swap(weak_ptr<T> & b) noexcept;
+
+    template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
+    template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
+  };
+
+  template<class T, class U>
+    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
+
+  template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef ... element_type;
+
+
+
+

element_type is T when T is not an array type, and U when T is U[] or U[N].

+
+
+
+

constructors

+
+
+
weak_ptr() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs an empty weak_ptr.

    +
    +
    Postconditions
    +
    +

    use_count() == 0.

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
+
+
+
+
+
weak_ptr(weak_ptr const & r) noexcept;
+
+
+
+
+
template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    If r is empty, constructs an empty weak_ptr; otherwise, constructs a weak_ptr that shares ownership with r as if by storing a copy of the pointer stored in r.

    +
    +
    Postconditions
    +
    +

    use_count() == r.use_count().

    +
    +
    +
    +
  • +
+
+
+
+
weak_ptr(weak_ptr && r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a weak_ptr that has the value r held.

    +
    +
    Postconditions
    +
    +

    r is empty.

    +
    +
    +
    +
  • +
+
+
+
+

aliasing constructors

+
+
+
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
+
+
+
+
+
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
+
+
+
+
+
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
+
+
+
+
+
Effects
+
+

Constructs a weak_ptr from r as if by using the corresponding converting/copy/move constructor, but stores p instead.

+
+
Postconditions
+
+

use_count() == r.use_count(). When !expired(), shared_ptr<T>(*this).get() == p.

+
+
+
+
+ + + + + +
+
Note
+
+These constructors are an extension, not present in std::weak_ptr. +
+
+
+
+

destructor

+
+
+
~weak_ptr() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Destroys this weak_ptr but has no effect on the object its stored pointer points to.

    +
    +
    +
    +
    +

    # assignment

    +
    +
  • +
+
+
+
+
weak_ptr & operator=(weak_ptr const & r) noexcept;
+
+
+
+
+
weak_ptr & operator=(weak_ptr && r) noexcept;
+
+
+
+
+
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
+
+
+
+
+
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to weak_ptr(r).swap(*this).

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. +
    +
    +
  • +
+
+
+
+

use_count

+
+
+
long use_count() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    0 if *this is empty; otherwise, the number of shared_ptr objects that share ownership with *this.

    +
    +
    +
    +
    +

    # expired

    +
    +
  • +
+
+
+
+
bool expired() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    use_count() == 0.

    +
    +
    +
    +
    +

    # empty

    +
    +
  • +
+
+
+
+
bool empty() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    true when *this is empty, false otherwise.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +This function is an extension, not present in std::weak_ptr. +
    +
    +
  • +
+
+
+
+

lock

+
+
+
shared_ptr<T> lock() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    expired()? shared_ptr<T>(): shared_ptr<T>(*this).

    +
    +
    +
    +
    +

    # reset

    +
    +
  • +
+
+
+
+
void reset() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to weak_ptr().swap(*this).

    +
    +
    +
    +
    +

    # swap

    +
    +
  • +
+
+
+
+
void swap(weak_ptr & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Exchanges the contents of the two smart pointers.

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
+
+
+
+
+
template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    See the description of operator<.

    +
    +
    +
    +
    +

    ## Free Functions

    +
    +
  • +
+
+
+
+

comparison

+
+
+
template<class T, class U>
+  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    An unspecified value such that

    +
    +
      +
    • +

      operator< is a strict weak ordering as described in section [lib.alg.sorting] of the C++ standard;

      +
    • +
    • +

      under the equivalence relation defined by operator<, !(a < b) && !(b < a), two weak_ptr instances +are equivalent if and only if they share ownership or are both empty.

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+Allows weak_ptr objects to be used as keys in associative containers. +
+
+
+
+

swap

+
+
+
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to a.swap(b).

    +
    +
    +
    +
    +

    ## Frequently Asked Questions

    +
    +
  • +
+
+
+
    +
  1. +

    Can an object create a weak_ptr to itself in its constructor?

    +

    No. A weak_ptr can only be created from a shared_ptr, and at object construction time no +shared_ptr to the object exists yet. Even if you could create a temporary shared_ptr to this, +it would go out of scope at the end of the constructor, and all weak_ptr instances would instantly expire.

    +
    +

    The solution is to make the constructor private, and supply a factory function that returns a shared_ptr:

    +
    +
    +
    +
    class X
    +{
    +private:
    +
    +    X();
    +
    +public:
    +
    +    static shared_ptr<X> create()
    +    {
    +        shared_ptr<X> px(new X);
    +        // create weak pointers from px here
    +        return px;
    +    }
    +};
    +
    +
    +
  2. +
+
+
+
+
+
+
+

make_shared: Creating shared_ptr

+
+
+

Description

+
+

The function templates make_shared and allocate_shared provide convenient, +safe and efficient ways to create shared_ptr objects.

+
+
+
+

Rationale

+
+

Consistent use of shared_ptr can eliminate the need to use an explicit +delete, but alone it provides no support in avoiding explicit new. There +were repeated requests from users for a factory function that creates an +object of a given type and returns a shared_ptr to it. Besides convenience +and style, such a function is also exception safe and considerably faster +because it can use a single allocation for both the object and its +corresponding control block, eliminating a significant portion of +shared_ptr construction overhead. This eliminates one of the major +efficiency complaints about shared_ptr.

+
+
+

The family of overloaded function templates, make_shared and +allocate_shared, were provided to address this need. make_shared uses the +global operator new to allocate memory, whereas allocate_shared uses an +user-supplied allocator, allowing finer control.

+
+
+

The rationale for choosing the name make_shared is that the expression +make_shared<Widget>() can be read aloud and conveys the intended meaning.

+
+
+

Originally the Boost function templates allocate_shared and make_shared +were provided for scalar objects only. There was a need to have efficient +allocation of array objects. One criticism of class template shared_array +was always the lack of a utility like make_shared that uses only a single +allocation. When shared_ptr was enhanced to support array types, additional +overloads of allocate_shared and make_shared were provided for array +types.

+
+
+
+

Synopsis

+
+

make_shared and allocate_shared are defined in +<boost/smart_ptr/make_shared.hpp>.

+
+
+
+
namespace boost {
+  // T is not an array
+  template<class T, class... Args>
+    shared_ptr<T> make_shared(Args&&... args);
+  template<class T, class A, class... Args>
+    shared_ptr<T> allocate_shared(const A& a, Args&&... args);
+
+  // T is an array of unknown bounds
+  template<class T>
+    shared_ptr<T> make_shared(std::size_t n);
+  template<class T, class A>
+    shared_ptr<T> allocate_shared(const A& a, std::size_t n);
+
+  // T is an array of known bounds
+  template<class T>
+    shared_ptr<T> make_shared();
+  template<class T, class A>
+    shared_ptr<T> allocate_shared(const A& a);
+
+  // T is an array of unknown bounds
+  template<class T> shared_ptr<T>
+    make_shared(std::size_t n, const remove_extent_t<T>& v);
+  template<class T, class A> shared_ptr<T>
+    allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
+
+  // T is an array of known bounds
+  template<class T>
+    shared_ptr<T> make_shared(const remove_extent_t<T>& v);
+  template<class T, class A>
+    shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
+
+  // T is not an array of unknown bounds
+  template<class T>
+    shared_ptr<T> make_shared_noinit();
+  template<class T, class A>
+    shared_ptr<T> allocate_shared_noinit(const A& a);
+
+  // T is an array of unknown bounds
+  template<class T>
+    shared_ptr<T> make_shared_noinit(std::size_t n);
+  template<class T, class A>
+    shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
+}
+
+
+
+
+

Common Requirements

+
+

The common requirements that apply to all make_shared and allocate_shared +overloads, unless specified otherwise, are described below.

+
+
+
+
Requires
+
+

A shall be an allocator. The copy constructor and destructor +of A shall not throw exceptions.

+
+
Effects
+
+

Allocates memory for an object of type T or n objects of U +(if T is an array type of the form U[] and n is determined by +arguments, as specified by the concrete overload). The object is initialized +from arguments as specified by the concrete overload. Uses a rebound copy of +a (for an unspecified value_type) to allocate memory. If an exception is +thrown, the functions have no effect.

+
+
Returns
+
+

A shared_ptr instance that stores and owns the address of the +newly constructed object.

+
+
Postconditions
+
+

r.get() != 0 and r.use_count() == 1, where r +is the return value.

+
+
Throws
+
+

std::bad_alloc, an exception thrown from A::allocate, or from the +initialization of the object.

+
+
Remarks
+
+
+
    +
  • +

    Performs no more than one memory allocation. This provides efficiency +equivalent to an intrusive smart pointer.

    +
  • +
  • +

    When an object of an array type is specified to be initialized to a value of +the same type v, this shall be interpreted to mean that each array element +of the object is initialized to the corresponding element from v.

    +
  • +
  • +

    When an object of an array type is specified to be value-initialized, this +shall be interpreted to mean that each array element of the object is +value-initialized.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be initialized to +a value v, or constructed from args..., make_shared shall perform +this initialization via the expression ::new(p) U(expr) (where +expr is v or std::forward<Args>(args)...) respectively) and p +has type void* and points to storage suitable to hold an object of type +U.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be initialized to +a value v, or constructed from args..., allocate_shared shall +perform this initialization via the expression +std::allocator_traits<A2>::construct(a2, p, expr) (where +expr is v or std::forward<Args>(args)...) respectively), p +points to storage suitable to hold an object of type U, and a2 of +type A2 is a potentially rebound copy a.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be +default-initialized, make_shared_noinit and allocate_shared_noinit shall +perform this initialization via the expression ::new(p) U, where +p has type void* and points to storage suitable to hold an object of +type U.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be +value-initialized, make_shared shall perform this initialization via the +expression ::new(p) U(), where p has type void* and points to +storage suitable to hold an object of type U.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be +value-initialized, allocate_shared shall perform this initialization via the +expression std::allocator_traits<A2>::construct(a2, p), where +p points to storage suitable to hold an object of type U and a2 of +type A2 is a potentially rebound copy of a.

    +
  • +
  • +

    Array elements are initialized in ascending order of their addresses.

    +
  • +
  • +

    When the lifetime of the object managed by the return value ends, or when +the initialization of an array element throws an exception, the initialized +elements should be destroyed in the reverse order of their construction.

    +
  • +
+
+
+
+
+
+ + + + + +
+
Note
+
+These functions will typically allocate more memory than the total size +of the element objects to allow for internal bookkeeping structures such as +the reference counts. +
+
+
+
+

Free Functions

+
+
+
template<class T, class... Args>
+  shared_ptr<T> make_shared(Args&&... args);
+
+
+
+
+
template<class T, class A, class... Args>
+  shared_ptr<T> allocate_shared(const A& a, Args&&... args);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    A shared_ptr to an object of type T, constructed from +args....

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = make_shared<int>();

    +
  • +
  • +

    auto p = make_shared<std::vector<int> >(16, 1);

    +
  • +
+
+
+
+
template<class T>
+  shared_ptr<T> make_shared(std::size_t n);
+
+
+
+
+
template<class T, class A>
+  shared_ptr<T> allocate_shared(const A& a, std::size_t n);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    A shared_ptr to a sequence of n value-initialized objects of +type remove_extent_t<T>.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = make_shared<double[]>(1024);

    +
  • +
  • +

    auto p = make_shared<double[][2][2]>(6);

    +
  • +
+
+
+
+
template<class T>
+  shared_ptr<T> make_shared();
+
+
+
+
+
template<class T, class A>
+  shared_ptr<T> allocate_shared(const A& a);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of known bounds.

    +
    +
    Returns
    +
    +

    A shared_ptr to a sequence of extent_v<T> value-initialized +objects of type remove_extent_t<T>.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = make_shared<double[1024]>();

    +
  • +
  • +

    auto p = make_shared<double[6][2][2]>();

    +
  • +
+
+
+
+
template<class T> shared_ptr<T>
+  make_shared(std::size_t n, const remove_extent_t<T>& v);
+
+
+
+
+
template<class T, class A> shared_ptr<T>
+  allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    A shared_ptr to a sequence of n objects of type +remove_extent_t<T>, each initialized to v.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = make_shared<double[]>(1024, 1.0);

    +
  • +
  • +

    auto p = make_shared<double[][2]>(6, {1.0, 0.0});

    +
  • +
  • +

    auto p = make_shared<std::vector<int>[]>(4, {1, 2});

    +
  • +
+
+
+
+
template<class T>
+  shared_ptr<T> make_shared(const remove_extent_t<T>& v);
+
+
+
+
+
template<class T, class A>
+  shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of known bounds.

    +
    +
    Returns
    +
    +

    A shared_ptr to a sequence of extent_v<T> objects of type +remove_extent_t<T>, each initialized to v.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = make_shared<double[1024]>(1.0);

    +
  • +
  • +

    auto p = make_shared<double[6][2]>({1.0, 0.0});

    +
  • +
  • +

    auto p = make_shared<std::vector<int>[4]>({1, 2});

    +
  • +
+
+
+
+
template<class T>
+  shared_ptr<T> make_shared_noinit();
+
+
+
+
+
template<class T, class A>
+  shared_ptr<T> allocate_shared_noinit(const A& a);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array, or is an array of known bounds.

    +
    +
    Returns
    +
    +

    A shared_ptr to a default-initialized object of type T, or a +sequence of extent_v<T> default-initialized objects of type +remove_extent_t<T>, respectively.

    +
    +
    Example
    +
    +

    auto p = make_shared_noinit<double[1024]>();

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  shared_ptr<T> make_shared_noinit(std::size_t n);
+
+
+
+
+
template<class T, class A>
+  shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    A shared_ptr to a sequence of n default-initialized objects +of type remove_extent_t<T>.

    +
    +
    Example
    +
    +

    auto p = make_shared_noinit<double[]>(1024);

    +
    +
    +
    +
  • +
+
+
+
+
+
+

enable_shared_from_this

+
+
+

Description

+
+

The class template enable_shared_from_this is used as a base class that allows +a shared_ptr or a weak_ptr to the current object to be obtained from within a +member function.

+
+
+

enable_shared_from_this<T> defines two member functions called shared_from_this +that return a shared_ptr<T> and shared_ptr<T const>, depending on constness, to +this. It also defines two member functions called weak_from_this that return a +corresponding weak_ptr.

+
+
+
+

Example

+
+
+
#include <boost/enable_shared_from_this.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cassert>
+
+class Y: public boost::enable_shared_from_this<Y>
+{
+public:
+
+    boost::shared_ptr<Y> f()
+    {
+        return shared_from_this();
+    }
+};
+
+int main()
+{
+    boost::shared_ptr<Y> p(new Y);
+    boost::shared_ptr<Y> q = p->f();
+    assert(p == q);
+    assert(!(p < q || q < p)); // p and q must share ownership
+}
+
+
+
+
+

Synopsis

+
+

enable_shared_from_this is defined in <boost/smart_ptr/enable_shared_from_this.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class enable_shared_from_this {
+  private:
+
+    // exposition only
+    weak_ptr<T> weak_this_;
+
+  protected:
+
+    enable_shared_from_this() = default;
+    ~enable_shared_from_this() = default;
+
+    enable_shared_from_this(const enable_shared_from_this&) noexcept;
+    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
+
+  public:
+
+    shared_ptr<T> shared_from_this();
+    shared_ptr<T const> shared_from_this() const;
+
+    weak_ptr<T> weak_from_this() noexcept;
+    weak_ptr<T const> weak_from_this() const noexcept;
+  }
+}
+
+
+
+
+

Members

+
+
+
enable_shared_from_this(enable_shared_from_this const &) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Default-constructs weak_this_.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +weak_this_ is not copied from the argument. +
    +
    +
  • +
+
+
+
+
enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +weak_this_ is unchanged. +
    +
    +
  • +
+
+
+
+
template<class T> shared_ptr<T> shared_from_this();
+
+
+
+
+
template<class T> shared_ptr<T const> shared_from_this() const;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    shared_ptr<T>(weak_this_).

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +These members throw bad_weak_ptr when *this is not owned by a shared_ptr. +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+
+

weak_this_ is initialized by shared_ptr to a copy of itself when it’s constructed by a pointer to *this. +For example, in the following code:

+
+
+
+
class Y: public boost::enable_shared_from_this<Y> {};
+
+int main()
+{
+    boost::shared_ptr<Y> p(new Y);
+}
+
+
+
+

the construction of p will automatically initialize p->weak_this_ to p.

+
+
+
+
+
+
template<class T> weak_ptr<T> weak_from_this() noexcept;
+
+
+
+
+
template<class T> weak_ptr<T const> weak_from_this() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    weak_this_.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Unlike shared_from_this(), weak_from_this() is valid in a destructor + and returns a weak_ptr that is expired() but still shares ownership + with other weak_ptr instances (if any) that refer to the object. +
    +
    +
  • +
+
+
+
+
+
+

enable_shared_from

+
+
+

Description

+
+

enable_shared_from is used as a base class that allows a shared_ptr or a +weak_ptr to be obtained given a raw pointer to the object, by using the +functions shared_from and weak_from.

+
+
+

enable_shared_from differs from enable_shared_from_this<T> by the fact +that it’s not a template, and is its recommended replacement for new code.

+
+
+
+

Example

+
+
+
#include <boost/smart_ptr/enable_shared_from.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cassert>
+
+class Y: public boost::enable_shared_from
+{
+public:
+
+    boost::shared_ptr<Y> f()
+    {
+        return boost::shared_from( this );
+    }
+};
+
+int main()
+{
+    boost::shared_ptr<Y> p(new Y);
+    boost::shared_ptr<Y> q = p->f();
+    assert(p == q);
+    assert(!(p < q || q < p)); // p and q must share ownership
+}
+
+
+
+
+

Synopsis

+
+

enable_shared_from is defined in <boost/smart_ptr/enable_shared_from.hpp>.

+
+
+
+
namespace boost {
+
+  class enable_shared_from: public enable_shared_from_this<enable_shared_from>
+  {
+  };
+
+  template<class T> shared_ptr<T> shared_from( T * p );
+  template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
+}
+
+
+
+
+

Functions

+
+
+
template<class T> shared_ptr<T> shared_from( T * p );
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    shared_ptr<T>( p->enable_shared_from::shared_from_this(), p ).

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Throws bad_weak_ptr when p is not owned by a shared_ptr. +
    +
    +
  • +
+
+
+
+
template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    weak_ptr<T>( p->enable_shared_from::weak_from_this(), p ).

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Unlike shared_from(this), weak_from(this) is valid in a destructor + and returns a weak_ptr that is expired() but still shares ownership + with other weak_ptr instances (if any) that refer to the object. +
    +
    +
  • +
+
+
+
+
+
+

make_unique: Creating unique_ptr

+
+
+

Description

+
+

The make_unique function templates provide convenient and safe ways to +create std::unique_ptr objects.

+
+
+
+

Rationale

+
+

The C++11 standard introduced std::unique_ptr but did not provide any +make_unique utility like std::make_shared that provided the same +exception safety and facility to avoid writing new expressions. Before it +was implemented by some standard library vendors (and prior to the C++14 +standard introducing std::make_unique), this library provided it due to +requests from users.

+
+
+

This library also provides additional overloads of make_unique for +default-initialization, when users do not need or want to incur the expense +of value-initialization. The C++ standard does not yet provide this +feature with std::make_unique.

+
+
+
+

Synopsis

+
+

make_unique is defined in <boost/smart_ptr/make_unique.hpp>.

+
+
+
+
namespace boost {
+  // T is not an array
+  template<class T, class... Args>
+    std::unique_ptr<T> make_unique(Args&&... args);
+
+  // T is not an array
+  template<class T>
+    std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
+
+  // T is an array of unknown bounds
+  template<class T>
+    std::unique_ptr<T> make_unique(std::size_t n);
+
+  // T is not an array
+  template<class T>
+    std::unique_ptr<T> make_unique_noinit();
+
+  // T is an array of unknown bounds
+  template<class T>
+    std::unique_ptr<T> make_unique_noinit(std::size_t n);
+}
+
+
+
+
+

Free Functions

+
+
+
template<class T, class... Args>
+  std::unique_ptr<T> make_unique(Args&&... args);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(new T(std::forward<Args>(args)...).

    +
    +
    Example
    +
    +

    auto p = make_unique<int>();

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(new T(std::move(v)).

    +
    +
    Example
    +
    +

    auto p = make_unique<std::vector<int> >({1, 2});

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  std::unique_ptr<T> make_unique(std::size_t n);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(new remove_extent_t<T>[n]()).

    +
    +
    Example
    +
    +

    auto p = make_unique<double[]>(1024);

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  std::unique_ptr<T> make_unique_noinit();
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(new T).

    +
    +
    Example
    +
    +

    auto p = make_unique_noinit<double[1024]>();

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  std::unique_ptr<T> make_unique_noinit(std::size_t n);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(new remove_extent_t<T>[n]).

    +
    +
    Example
    +
    +

    auto p = make_unique_noinit<double[]>(1024);

    +
    +
    +
    +
  • +
+
+
+
+
+
+

allocate_unique: Creating unique_ptr

+
+
+

Description

+
+

The allocate_unique family of function templates provide convenient and safe +ways to obtain a std::unique_ptr that manages a new object created using an +allocator.

+
+
+
+

Rationale

+
+

The C++14 standard introduced std::make_unique which used operator new to +create new objects. However, there is no convenient facility in the standard +library to use an allocator for the creation of the objects managed by +std::unique_ptr. Users writing allocator aware code have often requested an +allocate_unique factory function. This function is to std::unique_ptr what +std::allocate_shared is to std::shared_ptr.

+
+
+
+

Synopsis

+
+

allocate_unique is defined in <boost/smart_ptr/allocate_unique.hpp>.

+
+
+
+
namespace boost {
+  template<class T, class A>
+  class alloc_deleter;
+
+  template<class T, class A>
+  using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>;
+
+  // T is not an array
+  template<class T, class A, class... Args>
+    std::unique_ptr<T, alloc_deleter<T, A>>
+      allocate_unique(const A& a, Args&&... args);
+
+  // T is not an array
+  template<class T, class A>
+    std::unique_ptr<T, alloc_deleter<T, A>>
+      allocate_unique(const A& a, type_identity_t<T>&& v);
+
+  // T is an array of unknown bounds
+  template<class T, class A>
+    std::unique_ptr<T, alloc_deleter<T, A>>
+      allocate_unique(const A& a, std::size_t n);
+
+  // T is an array of known bounds
+  template<class T, class A>
+    std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
+      allocate_unique(const A& a);
+
+  // T is an array of unknown bounds
+  template<class T, class A>
+    std::unique_ptr<T, alloc_deleter<T, A>>
+      allocate_unique(const A& a, std::size_t n, const type_identity_t<T>& v);
+
+  // T is an array of known bounds
+  template<class T, class A>
+    std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
+      allocate_unique(const A& a, const type_identity_t<T>& v);
+
+  // T is not an array
+  template<class T, class A>
+    std::unique_ptr<T, alloc_noinit_deleter<T, A>>
+      allocate_unique_noinit(const A& a);
+
+  // T is an array of unknown bounds
+  template<class T, class A>
+    std::unique_ptr<T, alloc_noinit_deleter<T, A>>
+      allocate_unique(const A& a, std::size_t n);
+
+  // T is an array of known bounds
+  template<class T, class A>
+    std::unique_ptr<remove_extent_t<T>[], alloc_noinit_deleter<T, A>>
+      allocate_unique_noinit(const A& a);
+}
+
+
+
+
+

Common Requirements

+
+

The common requirements that apply to all allocate_unique and +allocate_unique_noinit overloads, unless specified otherwise, are described +below.

+
+
+
+
Requires
+
+

A shall be an allocator. The copy constructor and destructor +of A shall not throw exceptions.

+
+
Effects
+
+

Allocates memory for an object of type T or n objects of U +(if T is an array type of the form U[] and n is determined by +arguments, as specified by the concrete overload). The object is initialized +from arguments as specified by the concrete overload. Uses a rebound copy of +a (for an unspecified value_type) to allocate memory. If an exception is +thrown, the functions have no effect.

+
+
Returns
+
+

A std::unique_ptr instance that stores and owns the address of the +newly constructed object.

+
+
Postconditions
+
+

r.get() != 0, where r is the return value.

+
+
Throws
+
+

An exception thrown from A::allocate, or from the initialization of +the object.

+
+
Remarks
+
+
+
    +
  • +

    When an object of an array type is specified to be initialized to a value of +the same type v, this shall be interpreted to mean that each array element +of the object is initialized to the corresponding element from v.

    +
  • +
  • +

    When an object of an array type is specified to be value-initialized, this +shall be interpreted to mean that each array element of the object is +value-initialized.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be initialized to a +value v, or constructed from args..., allocate_unique shall perform this +initialization via the expression +std::allocator_traits<A2>::construct(a2, p, expr) (where expr is v or +std::forward<Args>(args)...) respectively), p points to storage suitable +to hold an object of type U, and a2 of type A2 is a potentially rebound +copy of a.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be +default-initialized, allocate_unique_noinit shall perform this initialization +via the expression ::new(p) U, where p has type void* and points to +storage suitable to hold an object of type U.

    +
  • +
  • +

    When a (sub)object of non-array type U is specified to be +value-initialized, allocate_unique shall perform this initialization via the +expression std::allocator_traits<A2>::construct(a2, p), where p points to +storage suitable to hold an object of type U and a2 of type A2 is a +potentially rebound copy of a.

    +
  • +
  • +

    Array elements are initialized in ascending order of their addresses.

    +
  • +
  • +

    When the lifetime of the object managed by the return value ends, or when the +initialization of an array element throws an exception, the initialized +elements should be destroyed in the reverse order of their construction.

    +
  • +
+
+
+
+
+
+
+

Free Functions

+
+
+
template<class T, class A, class... Args>
+  std::unique_ptr<T, alloc_deleter<T, A>>
+    allocate_unique(const A& a, Args&&... args);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to an object of type T, constructed from +args....

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = allocate_unique<int>(a);

    +
  • +
  • +

    auto p = allocate_unique<std::vector<int>>(a, 16, 1);

    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<T, alloc_deleter<T, A>>
+    allocate_unique(const A& a, type_identity_t<T>&& v);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to an object of type T, constructed from v.

    +
    +
    Example
    +
    +

    auto p = allocate_unique<std::vector<int>>(a, {1, 2});

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<T, alloc_deleter<T, A>>
+    allocate_unique(const A& a, std::size_t n);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a sequence of n value-initialized objects of +type remove_extent_t<T>.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = allocate_unique<double[]>(a, 1024);

    +
  • +
  • +

    auto p = allocate_unique<double[][2][2]>(a, 6);

    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
+    allocate_unique(const A& a);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of known bounds.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a sequence of extent_v<T> value-initialized +objects of type remove_extent_t<T>.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = allocate_unique<double[1024]>(a);

    +
  • +
  • +

    auto p = allocate_unique<double[6][2][2]>(a);

    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<T, alloc_deleter<T, A>>
+    allocate_unique(const A& a, std::size_t n, const type_identity_t<T>& v);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a sequence of n objects of type +remove_extent_t<T>, each initialized to v.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = allocate_unique<double[]>(a, 1024, 1.0);

    +
  • +
  • +

    auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});

    +
  • +
  • +

    auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});

    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
+    allocate_unique(const A& a, const type_identity_t<T>& v);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of known bounds.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a sequence of extent_v<T> objects of type +remove_extent_t<T>, each initialized to v.

    +
    +
    Examples
    +
    +
    +
  • +
  • +

    auto p = allocate_unique<double[1024]>(a, 1.0);

    +
  • +
  • +

    auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});

    +
  • +
  • +

    auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});

    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<T, alloc_noinit_deleter<T, A>>
+    allocate_unique_noinit(const A& a);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is not an array.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a default-initialized object of type T.

    +
    +
    Example
    +
    +

    auto p = allocate_unique_noinit<double>(a);

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<T, alloc_noinit_deleter<T, A>>
+    allocate_unique(const A& a, std::size_t n);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of unknown bounds.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a sequence of n default-initialized objects +of type remove_extent_t<T>.

    +
    +
    Example
    +
    +

    auto p = allocate_unique_noinit<double[]>(a, 1024);

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class A>
+  std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>>
+    allocate_unique_noinit(const A& a);
+
+
+
+
    +
  • +

    +
    +
    +
    Constraints
    +
    +

    T is an array of known bounds.

    +
    +
    Returns
    +
    +

    A std::unique_ptr to a sequence of extent_v<T> +default-initialized objects of type remove_extent_t<T>.

    +
    +
    Example
    +
    +

    auto p = allocate_unique_noinit<double[1024]>(a);

    +
    +
    +
    +
  • +
+
+
+
+

Deleter

+
+

Class template alloc_deleter is the deleter used by the allocate_unique +functions.

+
+
+

Synopsis

+
+
+
namespace boost {
+  template<class T, class A>
+  class alloc_deleter {
+  public:
+    using pointer = unspecified;
+
+    explicit alloc_deleter(const A& a) noexcept;
+
+    void operator()(pointer p);
+  };
+}
+
+
+
+
+

Members

+
+
+
using pointer = unspecified;
+
+
+
+
    +
  • +

    +
    +

    A type that satisfies NullablePointer.

    +
    +
  • +
+
+
+
+
explicit alloc_deleter(const A& a) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Initializes the stored allocator from a.

    +
    +
    +
    +
  • +
+
+
+
+
void operator()(pointer p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Destroys the objects and deallocates the storage referenced by p, +using the stored allocator.

    +
    +
    +
    +
  • +
+
+
+
+
+
+
+

intrusive_ptr: Managing Objects with Embedded Counts

+
+
+

Description

+
+

The intrusive_ptr class template stores a pointer to an object with an embedded reference count. +Every new intrusive_ptr instance increments the reference count by using an unqualified call to the +function intrusive_ptr_add_ref, passing it the pointer as an argument. Similarly, when an intrusive_ptr +is destroyed, it calls intrusive_ptr_release; this function is responsible for destroying the object when +its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. +On compilers that support argument-dependent lookup, intrusive_ptr_add_ref and intrusive_ptr_release should +be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace +boost. The library provides a helper base class template intrusive_ref_counter which +may help adding support for intrusive_ptr to user types.

+
+
+

The class template is parameterized on T, the type of the object pointed to. intrusive_ptr<T> can be implicitly +converted to intrusive_ptr<U> whenever T* can be implicitly converted to U*.

+
+
+

The main reasons to use intrusive_ptr are:

+
+
+
    +
  • +

    Some existing frameworks or OSes provide objects with embedded reference counts;

    +
  • +
  • +

    The memory footprint of intrusive_ptr is the same as the corresponding raw pointer;

    +
  • +
  • +

    intrusive_ptr<T> can be constructed from an arbitrary raw pointer of type T*.

    +
  • +
+
+
+

As a general rule, if it isn’t obvious whether intrusive_ptr better fits your needs than shared_ptr, try a shared_ptr-based design first.

+
+
+
+

Synopsis

+
+

intrusive_ptr is defined in <boost/smart_ptr/intrusive_ptr.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class intrusive_ptr {
+  public:
+
+    typedef T element_type;
+
+    intrusive_ptr() noexcept;
+    intrusive_ptr(T * p, bool add_ref = true);
+
+    intrusive_ptr(intrusive_ptr const & r);
+    template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
+
+    intrusive_ptr(intrusive_ptr && r);
+    template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
+
+    ~intrusive_ptr();
+
+    intrusive_ptr & operator=(intrusive_ptr const & r);
+    template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
+    intrusive_ptr & operator=(T * r);
+
+    intrusive_ptr & operator=(intrusive_ptr && r);
+    template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
+
+    void reset();
+    void reset(T * r);
+    void reset(T * r, bool add_ref);
+
+    T & operator*() const noexcept;
+    T * operator->() const noexcept;
+    T * get() const noexcept;
+    T * detach() noexcept;
+
+    explicit operator bool () const noexcept;
+
+    void swap(intrusive_ptr & b) noexcept;
+  };
+
+  template<class T, class U>
+    bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
+
+  template<class T, class U>
+    bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
+
+  template<class T>
+    bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
+
+  template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
+
+  template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
+
+  template<class T, class U>
+    intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+  template<class E, class T, class Y>
+    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
+      intrusive_ptr<Y> const & p);
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef T element_type;
+
+
+
+

Provides the type of the template parameter T.

+
+
+
+

constructors

+
+
+
intrusive_ptr() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Postconditions
    +
    +

    get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+
intrusive_ptr(T * p, bool add_ref = true);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    if(p != 0 && add_ref) intrusive_ptr_add_ref(p);.

    +
    +
    Postconditions
    +
    +

    get() == p.

    +
    +
    +
    +
  • +
+
+
+
+
intrusive_ptr(intrusive_ptr const & r);
+
+
+
+
+
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);.

    +
    +
    Postconditions
    +
    +

    get() == r.get().

    +
    +
    +
    +
  • +
+
+
+
+
intrusive_ptr(intrusive_ptr && r);
+
+
+
+
+
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Postconditions
    +
    +

    get() equals the old value of r.get(). r.get() == 0.

    +
    +
    +
    +
    +

    # destructor

    +
    +
  • +
+
+
+
+
~intrusive_ptr();
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    if(get() != 0) intrusive_ptr_release(get());.

    +
    +
    +
    +
    +

    # assignment

    +
    +
  • +
+
+
+
+
intrusive_ptr & operator=(intrusive_ptr const & r);
+
+
+
+
+
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
+
+
+
+
+
intrusive_ptr & operator=(T * r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to intrusive_ptr(r).swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+
intrusive_ptr & operator=(intrusive_ptr && r);
+
+
+
+
+
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to intrusive_ptr(std::move(r)).swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+

reset

+
+
+
void reset();
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to intrusive_ptr().swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
void reset(T * r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to intrusive_ptr(r).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
void reset(T * r, bool add_ref);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to intrusive_ptr(r, add_ref).swap(*this).

    +
    +
    +
    +
    +

    # indirection

    +
    +
  • +
+
+
+
+
T & operator*() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requirements
    +
    +

    get() != 0.

    +
    +
    Returns
    +
    +

    *get().

    +
    +
    +
    +
  • +
+
+
+
+
T * operator->() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requirements
    +
    +

    get() != 0.

    +
    +
    Returns
    +
    +

    get().

    +
    +
    +
    +
  • +
+
+
+
+

get

+
+
+
T * get() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    the stored pointer.

    +
    +
    +
    +
    +

    # detach

    +
    +
  • +
+
+
+
+
T * detach() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    the stored pointer.

    +
    +
    Postconditions
    +
    +

    get() == 0.

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+The returned pointer has an elevated reference count. This allows conversion of an intrusive_ptr +back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference. +It can be viewed as the complement of the non-reference-incrementing constructor. +
+
+
+ + + + + +
+
Caution
+
+Using detach escapes the safety of automatic reference counting provided by intrusive_ptr. +It should by used only where strictly necessary (such as when interfacing to an existing API), and when +the implications are thoroughly understood. +
+
+
+
+

conversions

+
+
+
explicit operator bool () const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    get() != 0.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +This conversion operator allows intrusive_ptr objects to be used in boolean contexts, +like if (p && p->valid()) {}. +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+On C++03 compilers, the return value is of an unspecified type. +
+
+
+
+

swap

+
+
+
void swap(intrusive_ptr & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Exchanges the contents of the two smart pointers.

    +
    +
    +
    +
    +

    ## Free Functions

    +
    +
  • +
+
+
+
+

comparison

+
+
+
template<class T, class U>
+  bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() == b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() != b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() == b.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() != b.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a == b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a != b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T>
+  bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    std::less<T *>()(a.get(), b.get()).

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Allows intrusive_ptr objects to be used as keys in associative containers. +
    +
    +
  • +
+
+
+
+

swap

+
+
+
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to a.swap(b).

    +
    +
    +
    +
    +

    # get_pointer

    +
    +
  • +
+
+
+
+
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get().

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Provided as an aid to generic programming. Used by mem_fn. +
    +
    +
  • +
+
+
+
+

static_pointer_cast

+
+
+
template<class T, class U>
+  intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    intrusive_ptr<T>(static_cast<T*>(r.get())).

    +
    +
    +
    +
    +

    # const_pointer_cast

    +
    +
  • +
+
+
+
+
template<class T, class U>
+  intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    intrusive_ptr<T>(const_cast<T*>(r.get())).

    +
    +
    +
    +
    +

    # dynamic_pointer_cast

    +
    +
  • +
+
+
+
+
template<class T, class U>
+  intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    intrusive_ptr<T>(dynamic_cast<T*>(r.get())).

    +
    +
    +
    +
    +

    # operator<<

    +
    +
  • +
+
+
+
+
template<class E, class T, class Y>
+  std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
+    intrusive_ptr<Y> const & p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    os << p.get();.

    +
    +
    Returns
    +
    +

    os.

    +
    +
    +
    +
  • +
+
+
+
+
+
+
+

intrusive_ref_counter

+
+
+

Description

+
+

The intrusive_ref_counter class template implements a reference counter for +a derived user’s class that is intended to be used with intrusive_ptr. The +base class has associated intrusive_ptr_add_ref and intrusive_ptr_release +functions which modify the reference counter as needed and destroy the user’s +object when the counter drops to zero.

+
+
+

The class template is parameterized on Derived and CounterPolicy +parameters. The first parameter is the user’s class that derives from +intrusive_ref_counter. This type is needed in order to destroy the object +correctly when there are no references to it left.

+
+
+

The second parameter is a policy that defines the nature of the reference +counter. The library provides two such policies: thread_unsafe_counter and +thread_safe_counter. The former instructs the intrusive_ref_counter base +class to use a counter only suitable for a single-threaded use. Pointers to a +single object that uses this kind of reference counter must not be used in +different threads. The latter policy makes the reference counter thread-safe, +unless the target platform doesn’t support threading. Since in modern systems +support for threading is common, the default counter policy is +thread_safe_counter.

+
+
+
+

Synopsis

+
+

intrusive_ref_counter is defined in +<boost/smart_ptr/intrusive_ref_counter.hpp>.

+
+
+
+
namespace boost {
+  struct thread_unsafe_counter;
+  struct thread_safe_counter;
+
+  template<class Derived, class CounterPolicy = thread_safe_counter>
+  class intrusive_ref_counter {
+  public:
+    intrusive_ref_counter() noexcept;
+    intrusive_ref_counter(const intrusive_ref_counter& v) noexcept;
+
+    intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
+
+    unsigned int use_count() const noexcept;
+
+  protected:
+    ~intrusive_ref_counter() = default;
+  };
+
+  template<class Derived, class CounterPolicy>
+    void intrusive_ptr_add_ref(
+      const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+
+  template<class Derived, class CounterPolicy>
+    void intrusive_ptr_release(
+      const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+}
+
+
+
+
+

Members

+
+

Constructors

+
+
+
intrusive_ref_counter() noexcept;
+
+
+
+
+
intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Postconditions
    +
    +

    use_count() == 0.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The pointer to the constructed object is expected to be passed to +intrusive_ptr constructor, assignment operator or reset method, which +would increment the reference counter. +
    +
    +
  • +
+
+
+
+

Destructor

+
+
+
~intrusive_ref_counter();
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Destroys the counter object.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The destructor is protected so that the object can only be destroyed +through the Derived class. +
    +
    +
  • +
+
+
+
+

Assignment

+
+
+
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Does nothing, reference counter is not modified.

    +
    +
    +
    +
    +

    # use_count

    +
    +
  • +
+
+
+
+
unsigned int use_count() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The current value of the reference counter.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The returned value may not be actual in multi-threaded applications. +
    +
    +
  • +
+
+
+
+
+

Free Functions

+
+

intrusive_ptr_add_ref

+
+
+
template<class Derived, class CounterPolicy>
+  void intrusive_ptr_add_ref(
+    const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Increments the reference counter.

    +
    +
    +
    +
    +

    # intrusive_ptr_release

    +
    +
  • +
+
+
+
+
template<class Derived, class CounterPolicy>
+  void intrusive_ptr_release(
+    const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Decrements the reference counter. If the reference counter reaches +0, calls delete static_cast<const Derived*>(p).

    +
    +
    +
    +
  • +
+
+
+
+
+
+
+

local_shared_ptr: Shared Ownership within a Single Thread

+
+
+

Description

+
+

local_shared_ptr is nearly identical to shared_ptr, with the only difference of note being that its reference count is +updated with non-atomic operations. As such, a local_shared_ptr and all its copies must reside in (be local to) a single +thread (hence the name.)

+
+
+

local_shared_ptr can be converted to shared_ptr and vice versa. Creating a local_shared_ptr from a shared_ptr creates +a new local reference count; this means that two local_shared_ptr instances, both created from the same shared_ptr, refer +to the same object but don’t share the same count, and as such, can safely be used by two different threads.

+
+
+
Code Example 9. Two local_shared_ptr instances created from a shared_ptr
+
+
shared_ptr<X> p1( new X );
+
+local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
+local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1
+
+
+
+

Creating the second local_shared_ptr from the first one, however, does lead to the two sharing the same count:

+
+
+
Code Example 10. A local_shared_ptr created from another local_shared_ptr
+
+
shared_ptr<X> p1( new X );
+
+local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
+local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2
+
+
+
+

Two shared_ptr instances created from the same local_shared_ptr do share ownership:

+
+
+
Code Example 11. Two shared_ptr instances created from a local_shared_ptr
+
+
local_shared_ptr<X> p1( new X );
+
+shared_ptr<X> p2( p1 ); // p2.use_count() == 2
+shared_ptr<X> p3( p1 ); // p3.use_count() == 3
+
+
+
+

Here p2.use_count() is 2, because p1 holds a reference, too.

+
+
+

One can think of local_shared_ptr<T> as shared_ptr<shared_ptr<T>>, with the outer shared_ptr using non-atomic operations for +its count. Converting from local_shared_ptr to shared_ptr gives you a copy of the inner shared_ptr; converting from shared_ptr +wraps it into an outer shared_ptr with a non-atomic use count (conceptually speaking) and returns the result.

+
+
+
+

Synopsis

+
+

local_shared_ptr is defined in <boost/smart_ptr/local_shared_ptr.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class local_shared_ptr {
+  public:
+
+    typedef /*see below*/ element_type;
+
+    // constructors
+
+    constexpr local_shared_ptr() noexcept;
+    constexpr local_shared_ptr(std::nullptr_t) noexcept;
+
+    template<class Y> explicit local_shared_ptr(Y * p);
+
+    template<class Y, class D> local_shared_ptr(Y * p, D d);
+    template<class D> local_shared_ptr(std::nullptr_t p, D d);
+
+    template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
+    template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
+
+    local_shared_ptr(local_shared_ptr const & r) noexcept;
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
+
+    local_shared_ptr(local_shared_ptr && r) noexcept;
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
+
+    template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
+    template<class Y> local_shared_ptr( shared_ptr<Y> && r );
+
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
+
+    template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
+
+    // destructor
+
+    ~local_shared_ptr() noexcept;
+
+    // assignment
+
+    local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
+    template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
+
+    local_shared_ptr & operator=(local_shared_ptr const && r) noexcept;
+    template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept;
+
+    template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
+
+    local_shared_ptr & operator=(std::nullptr_t) noexcept;
+
+    // reset
+
+    void reset() noexcept;
+
+    template<class Y> void reset(Y * p);
+    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(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+    template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
+
+    // accessors
+
+    T & operator*() const noexcept; // only valid when T is not an array type
+    T * operator->() const noexcept; // only valid when T is not an array type
+
+    // only valid when T is an array type
+    element_type & operator[](std::ptrdiff_t i) const noexcept;
+
+    element_type * get() const noexcept;
+
+    long local_use_count() const noexcept;
+
+    // conversions
+
+    explicit operator bool() const noexcept;
+
+    template<class Y> operator shared_ptr<Y>() const noexcept;
+    template<class Y> operator weak_ptr<Y>() const noexcept;
+
+    // swap
+
+    void swap(local_shared_ptr & b) noexcept;
+
+    // owner_before
+
+    template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
+  };
+
+  // comparisons
+
+  template<class T, class U>
+    bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+  template<class T, class U>
+    bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+  template<class T, class U>
+    bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+  template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+
+  template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+  template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+
+  template<class T, class U>
+    bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+  // swap
+
+  template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
+
+  // get_pointer
+
+  template<class T>
+    typename local_shared_ptr<T>::element_type *
+      get_pointer(local_shared_ptr<T> const & p) noexcept;
+
+  // casts
+
+  template<class T, class U>
+    local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  template<class T, class U>
+    local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+  // stream I/O
+
+  template<class E, class T, class Y>
+    std::basic_ostream<E, T> &
+      operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
+
+  // get_deleter
+
+  template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept;
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef ... element_type;
+
+
+
+

element_type is T when T is not an array type, and U when T is U[] or U[N].

+
+
+
+

default constructor

+
+
+
constexpr local_shared_ptr() noexcept;
+
+
+
+
+
constexpr local_shared_ptr(std::nullptr_t) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs an empty local_shared_ptr.

    +
    +
    Postconditions
    +
    +

    local_use_count() == 0 && get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+

pointer constructor

+
+
+
template<class Y> explicit local_shared_ptr(Y * p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a local_shared_ptr that owns shared_ptr<T>( p ).

    +
    +
    Postconditions
    +
    +

    local_use_count() == 1 && get() == p.

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    +
    +
  • +
+
+
+
+

constructors taking a deleter

+
+
+
template<class Y, class D> local_shared_ptr(Y * p, D d);
+
+
+
+
+
template<class D> local_shared_ptr(std::nullptr_t p, D d);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a local_shared_ptr that owns shared_ptr<T>( p, d ).

    +
    +
    Postconditions
    +
    +

    local_use_count() == 1 && get() == p.

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
+
+
+
+
+
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a local_shared_ptr that owns shared_ptr<T>( p, d, a ).

    +
    +
    Postconditions
    +
    +

    local_use_count() == 1 && get() == p.

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    +
    +
  • +
+
+
+
+

copy and converting constructors

+
+
+
local_shared_ptr(local_shared_ptr const & r) noexcept;
+
+
+
+
+
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +

    If r is empty, constructs an empty local_shared_ptr; otherwise, constructs a local_shared_ptr that shares ownership with r.

    +
    +
    Postconditions
    +
    +

    get() == r.get() && local_use_count() == r.local_use_count().

    +
    +
    +
    +
  • +
+
+
+
+

move constructors

+
+
+
local_shared_ptr(local_shared_ptr && r) noexcept;
+
+
+
+
+
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +

    Move-constructs a local_shared_ptr from r.

    +
    +
    Postconditions
    +
    +

    *this contains the old value of r. r is empty and r.get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+

shared_ptr constructor

+
+
+
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
+
+
+
+
+
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a local_shared_ptr that owns r.

    +
    +
    Postconditions
    +
    +

    local_use_count() == 1. get() returns the old value of r.get().

    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    +
    +
  • +
+
+
+
+

aliasing constructor

+
+
+
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    constructs a local_shared_ptr that shares ownership with r and stores p.

    +
    +
    Postconditions
    +
    +

    get() == p && local_use_count() == r.local_use_count().

    +
    +
    +
    +
  • +
+
+
+
+

aliasing move constructor

+
+
+
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Move-constructs a local_shared_ptr from r, while storing p instead.

    +
    +
    Postconditions
    +
    +

    get() == p and local_use_count() equals the old count of r. r is empty and r.get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+

unique_ptr constructor

+
+
+
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    Y* should be convertible to T*.

    +
    +
    Effects
    +
    +
    +
      +
    • +

      When r.get() == 0, equivalent to local_shared_ptr();

      +
    • +
    • +

      Otherwise, constructs a local_shared_ptr that owns shared_ptr<T>( std::move(r) ).

      +
    • +
    +
    +
    +
    Throws
    +
    +

    std::bad_alloc, or an implementation-defined exception when a resource other than memory could not be obtained.

    +
    +
    Exception safety
    +
    +

    If an exception is thrown, the constructor has no effect.

    +
    +
    +
    +
  • +
+
+
+
+

destructor

+
+
+
~local_shared_ptr() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +
    +
      +
    • +

      If *this is empty, or shares ownership with another local_shared_ptr instance (local_use_count() > 1), there are no side effects.

      +
    • +
    • +

      Otherwise, destroys the owned shared_ptr.

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+
+

assignment

+
+
+
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
+
+
+
+
+
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(r).swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+
local_shared_ptr & operator=(local_shared_ptr && r) noexcept;
+
+
+
+
+
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept;
+
+
+
+
+
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(std::move(r)).swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+
local_shared_ptr & operator=(std::nullptr_t) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr().swap(*this).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+

reset

+
+
+
void reset() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr().swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> void reset(Y * p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(p).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y, class D> void reset(Y * p, D d);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(p, d).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y, class D, class A> void reset(Y * p, D d, A a);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(p, d, a).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(r, p).swap(*this).

    +
    +
    +
    +
  • +
+
+
+
+
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to local_shared_ptr(std::move(r), p).swap(*this).

    +
    +
    +
    +
    +

    # indirection

    +
    +
  • +
+
+
+
+
T & operator*() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T should not be an array type.

    +
    +
    Returns
    +
    +

    *get().

    +
    +
    +
    +
  • +
+
+
+
+
T * operator->() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T should not be an array type.

    +
    +
    Returns
    +
    +

    get().

    +
    +
    +
    +
  • +
+
+
+
+
element_type & operator[](std::ptrdiff_t i) const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T should be an array type. The stored pointer must not be 0. i >= 0. If T is U[N], i < N.

    +
    +
    Returns
    +
    +

    get()[i].

    +
    +
    +
    +
  • +
+
+
+
+

get

+
+
+
element_type * get() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The stored pointer.

    +
    +
    +
    +
    +

    # local_use_count

    +
    +
  • +
+
+
+
+
long local_use_count() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The number of local_shared_ptr objects, *this included, that share ownership with *this, or 0 when *this is empty.

    +
    +
    +
    +
    +

    # conversions

    +
    +
  • +
+
+
+
+
explicit operator bool() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    get() != 0.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +On C++03 compilers, the return value is of an unspecified type. +
    +
    +
  • +
+
+
+
+
template<class Y> operator shared_ptr<Y>() const noexcept;
+
+
+
+
+
template<class Y> operator weak_ptr<Y>() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    T* should be convertible to Y*.

    +
    +
    Returns
    +
    +

    a copy of the owned shared_ptr.

    +
    +
    +
    +
  • +
+
+
+
+

swap

+
+
+
void swap(local_shared_ptr & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Exchanges the contents of the two smart pointers.

    +
    +
    +
    +
    +

    # owner_before

    +
    +
  • +
+
+
+
+
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    See the description of operator<.

    +
    +
    +
    +
    +

    ## Free Functions

    +
    +
  • +
+
+
+
+

comparison

+
+
+
template<class T, class U>
+  bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+
+
+
+
template<class T, class U>
+  bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+
+
+
+
template<class T, class U>
+  bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() == b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+
+
+
+
template<class T, class U>
+  bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
+
+
+
+
+
template<class T, class U>
+  bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.get() != b.get().

    +
    +
    +
    +
  • +
+
+
+
+
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+
+
+
+
+
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get() == 0.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
+
+
+
+
+
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get() != 0.

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U>
+  bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    An unspecified value such that

    +
    +
      +
    • +

      operator< is a strict weak ordering as described in section [lib.alg.sorting] of the C++ standard;

      +
    • +
    • +

      under the equivalence relation defined by operator<, !(a < b) && !(b < a), two local_shared_ptr instances +are equivalent if and only if they share ownership or are both empty.

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+Allows local_shared_ptr objects to be used as keys in associative containers. +
+
+
+ + + + + +
+
Note
+
+The rest of the comparison operators are omitted by design. +
+
+
+
+

swap

+
+
+
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Equivalent to a.swap(b).

    +
    +
    +
    +
    +

    # get_pointer

    +
    +
  • +
+
+
+
+
template<class T>
+  typename local_shared_ptr<T>::element_type *
+    get_pointer(local_shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p.get().

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +Provided as an aid to generic programming. Used by mem_fn. +
    +
    +
  • +
+
+
+
+

static_pointer_cast

+
+
+
template<class T, class U>
+  local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression static_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +

    local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) ).

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Caution
+
+The seemingly equivalent expression local_shared_ptr<T>(static_cast<T*>(r.get())) will eventually +result in undefined behavior, attempting to delete the same object twice. +
+
+
+
+

const_pointer_cast

+
+
+
template<class T, class U>
+  local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression const_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +

    local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) ).

    +
    +
    +
    +
  • +
+
+
+
+

dynamic_pointer_cast

+
+
+
template<class T, class U>
+    local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression dynamic_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +
    +
      +
    • +

      When dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, local_shared_ptr<T>(r, p);

      +
    • +
    • +

      Otherwise, local_shared_ptr<T>().

      +
    • +
    +
    +
    +
    +
    +
  • +
+
+
+
+

reinterpret_pointer_cast

+
+
+
template<class T, class U>
+  local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression reinterpret_cast<T*>( (U*)0 ) must be well-formed.

    +
    +
    Returns
    +
    +

    local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) ).

    +
    +
    +
    +
  • +
+
+
+
+

operator<<

+
+
+
template<class E, class T, class Y>
+  std::basic_ostream<E, T> &
+    operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    os << p.get();.

    +
    +
    Returns
    +
    +

    os.

    +
    +
    +
    +
  • +
+
+
+
+

get_deleter

+
+
+
template<class D, class T>
+  D * get_deleter(local_shared_ptr<T> const & p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    If *this owns a shared_ptr instance p, get_deleter<D>( p ), otherwise 0.

    +
    +
    +
    +
  • +
+
+
+
+
+
+
+

make_local_shared: Creating local_shared_ptr

+
+
+

Description

+
+

The function templates make_local_shared and allocate_local_shared provide +convenient, safe and efficient ways to create local_shared_ptr objects. They +are analogous to make_shared and allocate_shared for shared_ptr.

+
+
+
+

Synopsis

+
+

make_local_shared and allocate_local_shared are defined in +<boost/smart_ptr/make_local_shared.hpp>.

+
+
+
+
namespace boost {
+  // T is not an array
+  template<class T, class... Args>
+    local_shared_ptr<T> make_local_shared(Args&&... args);
+  template<class T, class A, class... Args>
+    local_shared_ptr<T> allocate_local_shared(const A& a, Args&&... args);
+
+  // T is an array of unknown bounds
+  template<class T>
+    local_shared_ptr<T> make_local_shared(std::size_t n);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n);
+
+  // T is an array of known bounds
+  template<class T>
+    local_shared_ptr<T> make_local_shared();
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a);
+
+  // T is an array of unknown bounds
+  template<class T>
+    local_shared_ptr<T> make_local_shared(std::size_t n,
+      const remove_extent_t<T>& v);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n,
+      const remove_extent_t<T>& v);
+
+  // T is an array of known bounds
+  template<class T>
+    local_shared_ptr<T> make_local_shared(const remove_extent_t<T>& v);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared(const A& a,
+      const remove_extent_t<T>& v);
+
+  // T is not an array of known bounds
+  template<class T>
+    local_shared_ptr<T> make_local_shared_noinit();
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared_noinit(const A& a);
+
+  // T is an array of unknown bounds
+  template<class T>
+    local_shared_ptr<T> make_local_shared_noinit(std::size_t n);
+  template<class T, class A>
+    local_shared_ptr<T> allocate_local_shared_noinit(const A& a,
+      std::size_t n);
+}
+
+
+
+
+

Description

+
+

The requirements and effects of these functions are the same as make_shared +and allocate_shared, except that a local_shared_ptr is returned.

+
+
+
+
+
+

Generic Pointer Casts

+
+
+

Description

+
+

The pointer cast function templates (static_pointer_cast, +dynamic_pointer_cast, const_pointer_cast, and reinterpret_pointer_cast) +provide a way to write generic pointer castings for raw pointers, +std::shared_ptr and std::unique_ptr.

+
+
+

There is test and example code in +pointer_cast_test.cpp

+
+
+
+

Rationale

+
+

Boost smart pointers usually overload those functions to provide a mechanism +to emulate pointers casts. For example, shared_ptr<T> implements a static +pointer cast this way:

+
+
+
+
template<class T, class U>
+  shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p);
+
+
+
+

Pointer cast functions templates are overloads of static_pointer_cast, +dynamic_pointer_cast, const_pointer_cast, and reinterpret_pointer_cast +for raw pointers, std::shared_ptr and std::unique_ptr. This way when +developing pointer type independent classes, for example, memory managers or +shared memory compatible classes, the same code can be used for raw and smart +pointers.

+
+
+
+

Synopsis

+
+

The generic pointer casts are defined in <boost/pointer_cast.hpp>.

+
+
+
+
namespace boost {
+  template<class T, class U> T* static_pointer_cast(U* p) noexcept;
+  template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
+  template<class T, class U> T* const_pointer_cast(U* p) noexcept;
+  template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
+
+  template<class T, class U> std::shared_ptr<T>
+    static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+  template<class T, class U> std::shared_ptr<T>
+    dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+  template<class T, class U> std::shared_ptr<T>
+    const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+  template<class T, class U> std::shared_ptr<T>
+    reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+
+  template<class T, class U> std::unique_ptr<T>
+    static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+  template<class T, class U> std::unique_ptr<T>
+    dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+  template<class T, class U> std::unique_ptr<T>
+    const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+  template<class T, class U> std::unique_ptr<T>
+    reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+}
+
+
+
+
+

Free Functions

+
+

static_pointer_cast

+
+
+
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    static_cast<T*>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::shared_ptr<T>
+  static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    std::static_pointer_cast<T>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::unique_ptr<T>
+  static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression static_cast<T*>((U*)0) must be well-formed.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(static_cast<typename +std::unique_ptr<T>::element_type*>(p.release())).

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Caution
+
+The seemingly equivalent expression +std::unique_ptr<T>(static_cast<T*>(p.get())) will eventually result in +undefined behavior, attempting to delete the same object twice. +
+
+
+
+

dynamic_pointer_cast

+
+
+
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    dynamic_cast<T*>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::shared_ptr<T>
+  dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    std::dynamic_pointer_cast<T>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::unique_ptr<T>
+  dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +
    +
  • +
  • +

    The expression static_cast<T*>((U*)0) must be well-formed.

    +
  • +
  • +

    T must have a virtual destructor.

    +
    +
    +
    Returns
    +
    +
    +
  • +
  • +

    When dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get()) +returns a non-zero value, std::unique_ptr<T>(dynamic_cast<typename +std::unique_ptr<T>::element_type*>(p.release()));.

    +
  • +
  • +

    Otherwise, std::unique_ptr<T>().

    +
  • +
+
+
+
+

const_pointer_cast

+
+
+
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    const_cast<T*>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::shared_ptr<T>
+  const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    std::const_pointer_cast<T>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::unique_ptr<T>
+  const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression const_cast<T*>((U*)0) must be well-formed.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(const_cast<typename +std::unique_ptr<T>::element_type*>(p.release())).

    +
    +
    +
    +
  • +
+
+
+
+

reinterpret_pointer_cast

+
+
+
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    reinterpret_cast<T*>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::shared_ptr<T>
+  reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    std::reinterpret_pointer_cast<T>(p)

    +
    +
    +
    +
  • +
+
+
+
+
template<class T, class U> std::unique_ptr<T>
+  reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Requires
    +
    +

    The expression reinterpret_cast<T*>((U*)0) must be well-formed.

    +
    +
    Returns
    +
    +

    std::unique_ptr<T>(reinterpret_cast<typename +std::unique_ptr<T>::element_type*>(p.release())).

    +
    +
    +
    +
  • +
+
+
+
+
+

Example

+
+

The following example demonstrates how the generic pointer casts help us +create pointer independent code.

+
+
+
+
#include <boost/pointer_cast.hpp>
+#include <boost/shared_ptr.hpp>
+
+class base {
+public:
+  virtual ~base() { }
+};
+
+class derived : public base { };
+
+template<class Ptr>
+void check_if_it_is_derived(const Ptr& ptr)
+{
+  assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
+}
+
+int main()
+{
+  base* ptr = new derived;
+  boost::shared_ptr<base> sptr(new derived);
+
+  check_if_it_is_derived(ptr);
+  check_if_it_is_derived(sptr);
+
+  delete ptr;
+}
+
+
+
+
+
+
+

pointer_to_other

+
+
+

Description

+
+

The pointer_to_other utility provides a way, given a source pointer type, to obtain a pointer of the same type +to another pointee type.

+
+
+

There is test/example code in pointer_to_other_test.cpp.

+
+
+
+

Rationale

+
+

When building pointer independent classes, like memory managers, allocators, or containers, there is often a need to +define pointers generically, so that if a template parameter represents a pointer (for example, a raw or smart pointer +to an int), we can define another pointer of the same type to another pointee (a raw or smart pointer to a float.)

+
+
+
+
template <class IntPtr> class FloatPointerHolder
+{
+    // Let's define a pointer to a float
+
+    typedef typename boost::pointer_to_other
+        <IntPtr, float>::type float_ptr_t;
+
+    float_ptr_t float_ptr;
+};
+
+
+
+
+

Synopsis

+
+

pointer_to_other is defined in <boost/smart_ptr/pointer_to_other.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T, class U> struct pointer_to_other;
+
+  template<class T, class U,
+    template <class> class Sp>
+      struct pointer_to_other< Sp<T>, U >
+  {
+    typedef Sp<U> type;
+  };
+
+  template<class T, class T2, class U,
+    template <class, class> class Sp>
+      struct pointer_to_other< Sp<T, T2>, U >
+  {
+    typedef Sp<U, T2> type;
+  };
+
+  template<class T, class T2, class T3, class U,
+    template <class, class, class> class Sp>
+      struct pointer_to_other< Sp<T, T2, T3>, U >
+  {
+    typedef Sp<U, T2, T3> type;
+  };
+
+  template<class T, class U>
+    struct pointer_to_other< T*, U >
+  {
+    typedef U* type;
+  };
+}
+
+
+
+

If these definitions are not correct for a specific smart pointer, we can define a specialization of pointer_to_other.

+
+
+
+

Example

+
+
+
// Let's define a memory allocator that can
+// work with raw and smart pointers
+
+#include <boost/pointer_to_other.hpp>
+
+template <class VoidPtr>
+class memory_allocator
+{
+    // Predefine a memory_block
+
+    struct block;
+
+    // Define a pointer to a memory_block from a void pointer
+    // If VoidPtr is void *, block_ptr_t is block*
+    // If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block>
+
+    typedef typename boost::pointer_to_other
+        <VoidPtr, block>::type block_ptr_t;
+
+    struct block
+    {
+        std::size_t size;
+        block_ptr_t next_block;
+    };
+
+    block_ptr_t free_blocks;
+};
+
+
+
+

As we can see, using pointer_to_other we can create pointer independent code.

+
+
+
+
+
+

atomic_shared_ptr

+
+
+

Description

+
+

The class template atomic_shared_ptr<T> implements the interface of std::atomic +for a contained value of type shared_ptr<T>. Concurrent access to atomic_shared_ptr +is not a data race.

+
+
+
+

Synopsis

+
+

atomic_shared_ptr is defined in <boost/smart_ptr/atomic_shared_ptr.hpp>.

+
+
+
+
namespace boost {
+
+  template<class T> class atomic_shared_ptr {
+  private:
+
+    shared_ptr<T> p_; // exposition only
+
+    atomic_shared_ptr(const atomic_shared_ptr&) = delete;
+    atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete;
+
+  public:
+
+    constexpr atomic_shared_ptr() noexcept;
+    atomic_shared_ptr( shared_ptr<T> p ) noexcept;
+
+    atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
+
+    bool is_lock_free() const noexcept;
+
+    shared_ptr<T> load( int = 0 ) const noexcept;
+    operator shared_ptr<T>() const noexcept;
+
+    void store( shared_ptr<T> r, int = 0 ) noexcept;
+
+    shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
+
+    bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+    bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+
+    bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+    bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+    bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+  };
+}
+
+
+
+
+

Members

+
+
+
constexpr atomic_shared_ptr() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Default-initializes p_.

    +
    +
    +
    +
  • +
+
+
+
+
atomic_shared_ptr( shared_ptr<T> p ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Initializes p_ to p.

    +
    +
    +
    +
  • +
+
+
+
+
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    p_.swap(r).

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+
bool is_lock_free() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    false.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +This implementation is not lock-free. +
    +
    +
  • +
+
+
+
+
shared_ptr<T> load( int = 0 ) const noexcept;
+
+
+
+
+
operator shared_ptr<T>() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    p_.

    +
    +
    +
    +
    + + + + + +
    +
    Note
    +
    +The int argument is intended to be of type memory_order, but is ignored. + This implementation is lock-based and therefore always sequentially consistent. +
    +
    +
  • +
+
+
+
+
void store( shared_ptr<T> r, int = 0 ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    p_.swap(r).

    +
    +
    +
    +
  • +
+
+
+
+
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    p_.swap(r).

    +
    +
    Returns
    +
    +

    The old value of p_.

    +
    +
    +
    +
  • +
+
+
+
+
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+
+
+
+
+
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+
+
+
+
+
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
+
+
+
+
+
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    If p_ is equivalent to v, assigns w to p_, otherwise assigns p_ to v.

    +
    +
    Returns
    +
    +

    true if p_ was equivalent to v, false otherwise.

    +
    +
    Remarks
    +
    +

    Two shared_ptr instances are equivalent if they store the same pointer value and share ownership.

    +
    +
    +
    +
  • +
+
+
+
+
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+
+
+
+
+
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+
+
+
+
+
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
+
+
+
+
+
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    If p_ is equivalent to v, assigns std::move(w) to p_, otherwise assigns p_ to v.

    +
    +
    Returns
    +
    +

    true if p_ was equivalent to v, false otherwise.

    +
    +
    Remarks
    +
    +

    The old value of w is not preserved in either case.

    +
    +
    +
    +
  • +
+
+
+
+
+
+

Appendix A: Smart Pointer Programming Techniques

+
+
+

Using incomplete classes for implementation hiding

+
+

A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle:

+
+
+
+
class FILE;
+
+FILE * fopen(char const * name, char const * mode);
+void fread(FILE * f, void * data, size_t size);
+void fclose(FILE * f);
+
+
+
+

It is possible to express the above interface using shared_ptr, eliminating the need to manually call fclose:

+
+
+
+
class FILE;
+
+shared_ptr<FILE> fopen(char const * name, char const * mode);
+void fread(shared_ptr<FILE> f, void * data, size_t size);
+
+
+
+

This technique relies on shared_ptr’s ability to execute a custom deleter, eliminating the explicit call to fclose, and on the fact that shared_ptr<X> can be copied and destroyed when X is incomplete.

+
+
+
+

The "Pimpl" idiom

+
+

A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. shared_ptr can be used to implement a "Pimpl":

+
+
+
+
// file.hpp:
+
+class file
+{
+private:
+
+    class impl;
+    shared_ptr<impl> pimpl_;
+
+public:
+
+    file(char const * name, char const * mode);
+
+    // compiler generated members are fine and useful
+
+    void read(void * data, size_t size);
+};
+
+// file.cpp:
+
+#include "file.hpp"
+
+class file::impl
+{
+private:
+
+    impl(impl const &);
+    impl & operator=(impl const &);
+
+    // private data
+
+public:
+
+    impl(char const * name, char const * mode) { ... }
+    ~impl() { ... }
+    void read(void * data, size_t size) { ... }
+};
+
+file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
+{
+}
+
+void file::read(void * data, size_t size)
+{
+    pimpl_->read(data, size);
+}
+
+
+
+

The key thing to note here is that the compiler-generated copy constructor, assignment operator, and destructor all have a sensible meaning. As a result, file is CopyConstructible and Assignable, allowing its use in standard containers.

+
+
+
+

Using abstract classes for implementation hiding

+
+

Another widely used C++ idiom for separating inteface and implementation is to use abstract base classes and factory functions. +The abstract classes are sometimes called "interfaces" and the pattern is known as "interface-based programming". Again, +shared_ptr can be used as the return type of the factory functions:

+
+
+
+
// X.hpp:
+
+class X
+{
+public:
+
+    virtual void f() = 0;
+    virtual void g() = 0;
+
+protected:
+
+    ~X() {}
+};
+
+shared_ptr<X> createX();
+
+// X.cpp:
+
+class X_impl: public X
+{
+private:
+
+    X_impl(X_impl const &);
+    X_impl & operator=(X_impl const &);
+
+public:
+
+    virtual void f()
+    {
+      // ...
+    }
+
+    virtual void g()
+    {
+      // ...
+    }
+};
+
+shared_ptr<X> createX()
+{
+    shared_ptr<X> px(new X_impl);
+    return px;
+}
+
+
+
+

A key property of shared_ptr is that the allocation, construction, deallocation, and destruction details are captured at the point of construction, inside the factory function.

+
+
+

Note the protected and nonvirtual destructor in the example above. The client code cannot, and does not need to, delete a pointer to X; the shared_ptr<X> instance returned from createX will correctly call ~X_impl.

+
+
+
+

Preventing delete px.get()

+
+

It is often desirable to prevent client code from deleting a pointer that is being managed by shared_ptr. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter:

+
+
+
+
class X
+{
+private:
+
+    ~X();
+
+    class deleter;
+    friend class deleter;
+
+    class deleter
+    {
+    public:
+
+        void operator()(X * p) { delete p; }
+    };
+
+public:
+
+    static shared_ptr<X> create()
+    {
+        shared_ptr<X> px(new X, X::deleter());
+        return px;
+    }
+};
+
+
+
+
+

Encapsulating allocation details, wrapping factory functions

+
+

shared_ptr can be used in creating C++ wrappers over existing C style library interfaces that return raw pointers from their factory functions +to encapsulate allocation details. As an example, consider this interface, where CreateX might allocate X from its own private heap, ~X may +be inaccessible, or X may be incomplete:

+
+
+
+
X * CreateX();
+void DestroyX(X *);
+
+
+
+

The only way to reliably destroy a pointer returned by CreateX is to call DestroyX.

+
+
+

Here is how a shared_ptr-based wrapper may look like:

+
+
+
+
shared_ptr<X> createX()
+{
+    shared_ptr<X> px(CreateX(), DestroyX);
+    return px;
+}
+
+
+
+

Client code that calls createX still does not need to know how the object has been allocated, but now the destruction is automatic.

+
+
+
+

Using a shared_ptr to hold a pointer to a statically allocated object

+
+

Sometimes it is desirable to create a shared_ptr to an already existing object, so that the shared_ptr does not attempt to destroy the +object when there are no more references left. As an example, the factory function:

+
+
+
+
shared_ptr<X> createX();
+
+
+
+

in certain situations may need to return a pointer to a statically allocated X instance.

+
+
+

The solution is to use a custom deleter that does nothing:

+
+
+
+
struct null_deleter
+{
+    void operator()(void const *) const
+    {
+    }
+};
+
+static X x;
+
+shared_ptr<X> createX()
+{
+    shared_ptr<X> px(&x, null_deleter());
+    return px;
+}
+
+
+
+

The same technique works for any object known to outlive the pointer.

+
+
+
+

Using a shared_ptr to hold a pointer to a COM Object

+
+

Background: COM objects have an embedded reference count and two member functions that manipulate it. AddRef() increments the count. +Release() decrements the count and destroys itself when the count drops to zero.

+
+
+

It is possible to hold a pointer to a COM object in a shared_ptr:

+
+
+
+
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
+{
+    p->AddRef();
+    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
+    return pw;
+}
+
+
+
+

Note, however, that shared_ptr copies created from pw will not "register" in the embedded count of the COM object; +they will share the single reference created in make_shared_from_COM. Weak pointers created from pw will be invalidated when the last +shared_ptr is destroyed, regardless of whether the COM object itself is still alive.

+
+
+

As explained in the mem_fn documentation, you need to #define BOOST_MEM_FN_ENABLE_STDCALL first.

+
+
+
+

Using a shared_ptr to hold a pointer to an object with an embedded reference count

+
+

This is a generalization of the above technique. The example assumes that the object implements the two functions required by intrusive_ptr, +intrusive_ptr_add_ref and intrusive_ptr_release:

+
+
+
+
template<class T> struct intrusive_deleter
+{
+    void operator()(T * p)
+    {
+        if(p) intrusive_ptr_release(p);
+    }
+};
+
+shared_ptr<X> make_shared_from_intrusive(X * p)
+{
+    if(p) intrusive_ptr_add_ref(p);
+    shared_ptr<X> px(p, intrusive_deleter<X>());
+    return px;
+}
+
+
+
+
+

Using a shared_ptr to hold another shared ownership smart pointer

+
+

One of the design goals of shared_ptr is to be used in library interfaces. It is possible to encounter a situation where a library takes a +shared_ptr argument, but the object at hand is being managed by a different reference counted or linked smart pointer.

+
+
+

It is possible to exploit shared_ptr’s custom deleter feature to wrap this existing smart pointer behind a shared_ptr facade:

+
+
+
+
template<class P> struct smart_pointer_deleter
+{
+private:
+
+    P p_;
+
+public:
+
+    smart_pointer_deleter(P const & p): p_(p)
+    {
+    }
+
+    void operator()(void const *)
+    {
+        p_.reset();
+    }
+
+    P const & get() const
+    {
+        return p_;
+    }
+};
+
+shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
+{
+    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
+    return px;
+}
+
+
+
+

One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that p_.reset() doesn’t throw. +If this is not the case, p_.reset(); should be wrapped in a try {} catch(…​) {} block that ignores exceptions. In the (usually unlikely) event +when an exception is thrown and ignored, p_ will be released when the lifetime of the deleter ends. This happens when all references, including +weak pointers, are destroyed or reset.

+
+
+

Another twist is that it is possible, given the above shared_ptr instance, to recover the original smart pointer, using get_deleter:

+
+
+
+
void extract_another_from_shared(shared_ptr<X> px)
+{
+    typedef smart_pointer_deleter< another_ptr<X> > deleter;
+
+    if(deleter const * pd = get_deleter<deleter>(px))
+    {
+        another_ptr<X> qx = pd->get();
+    }
+    else
+    {
+        // not one of ours
+    }
+}
+
+
+
+
+

Obtaining a shared_ptr from a raw pointer

+
+

Sometimes it is necessary to obtain a shared_ptr given a raw pointer to an object that is already managed by another shared_ptr instance. Example:

+
+
+
+
void f(X * p)
+{
+    shared_ptr<X> px(???);
+}
+
+
+
+

Inside f, we’d like to create a shared_ptr to *p.

+
+
+

In the general case, this problem has no solution. One approach is to modify f to take a shared_ptr, if possible:

+
+
+
+
void f(shared_ptr<X> px);
+
+
+
+

The same transformation can be used for nonvirtual member functions, to convert the implicit this:

+
+
+
+
void X::f(int m);
+
+
+
+

would become a free function with a shared_ptr first argument:

+
+
+
+
void f(shared_ptr<X> this_, int m);
+
+
+
+

If f cannot be changed, but X uses intrusive counting, use make_shared_from_intrusive described above. Or, if it’s known that the shared_ptr created in f will never outlive the object, use a null deleter.

+
+
+
+

Obtaining a shared_ptr (weak_ptr) to this in a constructor

+
+

Some designs require objects to register themselves on construction with a central authority. When the registration routines take a shared_ptr, this leads to the question how could a constructor obtain a shared_ptr to this:

+
+
+
+
class X
+{
+public:
+
+    X()
+    {
+        shared_ptr<X> this_(???);
+    }
+};
+
+
+
+

In the general case, the problem cannot be solved. The X instance being constructed can be an automatic variable or a static variable; it can be created on the heap:

+
+
+
+
shared_ptr<X> px(new X);
+
+
+
+

but at construction time, px does not exist yet, and it is impossible to create another shared_ptr instance that shares ownership with it.

+
+
+

Depending on context, if the inner shared_ptr this_ doesn’t need to keep the object alive, use a null_deleter as explained here and here. +If X is supposed to always live on the heap, and be managed by a shared_ptr, use a static factory function:

+
+
+
+
class X
+{
+private:
+
+    X() { ... }
+
+public:
+
+    static shared_ptr<X> create()
+    {
+        shared_ptr<X> px(new X);
+        // use px as 'this_'
+        return px;
+    }
+};
+
+
+
+
+

Obtaining a shared_ptr to this

+
+

Sometimes it is needed to obtain a shared_ptr from this in a virtual member function under the assumption that this is already managed by a shared_ptr. +The transformations described in the previous technique cannot be applied.

+
+
+

A typical example:

+
+
+
+
class X
+{
+public:
+
+    virtual void f() = 0;
+
+protected:
+
+    ~X() {}
+};
+
+class Y
+{
+public:
+
+    virtual shared_ptr<X> getX() = 0;
+
+protected:
+
+    ~Y() {}
+};
+
+// --
+
+class impl: public X, public Y
+{
+public:
+
+    impl() { ... }
+
+    virtual void f() { ... }
+
+    virtual shared_ptr<X> getX()
+    {
+        shared_ptr<X> px(???);
+        return px;
+    }
+};
+
+
+
+

The solution is to keep a weak pointer to this as a member in impl:

+
+
+
+
class impl: public X, public Y
+{
+private:
+
+    weak_ptr<impl> weak_this;
+
+    impl(impl const &);
+    impl & operator=(impl const &);
+
+    impl() { ... }
+
+public:
+
+    static shared_ptr<impl> create()
+    {
+        shared_ptr<impl> pi(new impl);
+        pi->weak_this = pi;
+        return pi;
+    }
+
+    virtual void f() { ... }
+
+    virtual shared_ptr<X> getX()
+    {
+        shared_ptr<X> px(weak_this);
+        return px;
+    }
+};
+
+
+
+

The library now includes a helper class template enable_shared_from_this that can be used to encapsulate the solution:

+
+
+
+
class impl: public X, public Y, public enable_shared_from_this<impl>
+{
+public:
+
+    impl(impl const &);
+    impl & operator=(impl const &);
+
+public:
+
+    virtual void f() { ... }
+
+    virtual shared_ptr<X> getX()
+    {
+        return shared_from_this();
+    }
+}
+
+
+
+

Note that you no longer need to manually initialize the weak_ptr member in enable_shared_from_this. Constructing a shared_ptr to impl takes care of that.

+
+
+
+

Using shared_ptr as a smart counted handle

+
+

Some library interfaces use opaque handles, a variation of the incomplete class technique described above. An example:

+
+
+
+
typedef void * HANDLE;
+
+HANDLE CreateProcess();
+void CloseHandle(HANDLE);
+
+
+
+

Instead of a raw pointer, it is possible to use shared_ptr as the handle and get reference counting and automatic resource management for free:

+
+
+
+
typedef shared_ptr<void> handle;
+
+handle createProcess()
+{
+    shared_ptr<void> pv(CreateProcess(), CloseHandle);
+    return pv;
+}
+
+
+
+
+

Using shared_ptr to execute code on block exit

+
+

shared_ptr<void> can automatically execute cleanup code when control leaves a scope.

+
+
+
    +
  • +

    Executing f(p), where p is a pointer:

    +
    +
    +
    shared_ptr<void> guard(p, f);
    +
    +
    +
  • +
  • +

    Executing arbitrary code: f(x, y):

    +
    +
    +
    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
    +
    +
    +
  • +
+
+
+
+

Using shared_ptr<void> to hold an arbitrary object

+
+

shared_ptr<void> can act as a generic object pointer similar to void*. When a shared_ptr<void> instance constructed as:

+
+
+
+
shared_ptr<void> pv(new X);
+
+
+
+

is destroyed, it will correctly dispose of the X object by executing ~X.

+
+
+

This propery can be used in much the same manner as a raw void* is used to temporarily strip type information from an object pointer. +A shared_ptr<void> can later be cast back to the correct type by using static_pointer_cast.

+
+
+
+

Associating arbitrary data with heterogeneous shared_ptr instances

+
+

shared_ptr and weak_ptr support operator< comparisons required by standard associative containers such as std::map. This can be +used to non-intrusively associate arbitrary data with objects managed by shared_ptr:

+
+
+
+
typedef int Data;
+
+std::map<shared_ptr<void>, Data> userData;
+// or std::map<weak_ptr<void>, Data> userData; to not affect the lifetime
+
+shared_ptr<X> px(new X);
+shared_ptr<int> pi(new int(3));
+
+userData[px] = 42;
+userData[pi] = 91;
+
+
+
+
+

Using shared_ptr as a CopyConstructible mutex lock

+
+

Sometimes it’s necessary to return a mutex lock from a function, and a noncopyable lock cannot be returned by value. It is possible to use shared_ptr as a mutex lock:

+
+
+
+
class mutex
+{
+public:
+
+    void lock();
+    void unlock();
+};
+
+shared_ptr<mutex> lock(mutex & m)
+{
+    m.lock();
+    return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
+}
+
+
+
+

Better yet, the shared_ptr instance acting as a lock can be encapsulated in a dedicated shared_lock class:

+
+
+
+
class shared_lock
+{
+private:
+
+    shared_ptr<void> pv;
+
+public:
+
+    template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
+};
+
+
+
+

shared_lock can now be used as:

+
+
+
+
shared_lock lock(m);
+
+
+
+

Note that shared_lock is not templated on the mutex type, thanks to shared_ptr<void>’s ability to hide type information.

+
+
+
+

Using shared_ptr to wrap member function calls

+
+

shared_ptr implements the ownership semantics required from the Wrap/CallProxy scheme described in Bjarne Stroustrup’s article +"Wrapping C++ Member Function Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below:

+
+
+
+
template<class T> class pointer
+{
+private:
+
+    T * p_;
+
+public:
+
+    explicit pointer(T * p): p_(p)
+    {
+    }
+
+    shared_ptr<T> operator->() const
+    {
+        p_->prefix();
+        return shared_ptr<T>(p_, mem_fn(&T::suffix));
+    }
+};
+
+class X
+{
+private:
+
+    void prefix();
+    void suffix();
+    friend class pointer<X>;
+
+public:
+
+    void f();
+    void g();
+};
+
+int main()
+{
+    X x;
+
+    pointer<X> px(&x);
+
+    px->f();
+    px->g();
+}
+
+
+
+
+

Delayed deallocation

+
+

In some situations, a single px.reset() can trigger an expensive deallocation in a performance-critical region:

+
+
+
+
class X; // ~X is expensive
+
+class Y
+{
+    shared_ptr<X> px;
+
+public:
+
+    void f()
+    {
+        px.reset();
+    }
+};
+
+
+
+

The solution is to postpone the potential deallocation by moving px to a dedicated free list that can be periodically emptied when performance and response times are not an issue:

+
+
+
+
vector< shared_ptr<void> > free_list;
+
+class Y
+{
+    shared_ptr<X> px;
+
+public:
+
+    void f()
+    {
+        free_list.push_back(px);
+        px.reset();
+    }
+};
+
+// periodically invoke free_list.clear() when convenient
+
+
+
+

Another variation is to move the free list logic to the construction point by using a delayed deleter:

+
+
+
+
struct delayed_deleter
+{
+    template<class T> void operator()(T * p)
+    {
+        try
+        {
+            shared_ptr<void> pv(p);
+            free_list.push_back(pv);
+        }
+        catch(...)
+        {
+        }
+    }
+};
+
+
+
+
+

Weak pointers to objects not managed by a shared_ptr

+
+

Make the object hold a shared_ptr to itself, using a null_deleter:

+
+
+
+
class X
+{
+private:
+
+    shared_ptr<X> this_;
+    int i_;
+
+public:
+
+    explicit X(int i): this_(this, null_deleter()), i_(i)
+    {
+    }
+
+    // repeat in all constructors (including the copy constructor!)
+
+    X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
+    {
+    }
+
+    // do not forget to not assign this_ in the copy assignment
+
+    X & operator=(X const & rhs)
+    {
+        i_ = rhs.i_;
+    }
+
+    weak_ptr<X> get_weak_ptr() const { return this_; }
+};
+
+
+
+

When the object’s lifetime ends, X::this_ will be destroyed, and all weak pointers will automatically expire.

+
+
+
+
+
+

Appendix B: History and Acknowledgments

+
+
+

Summer 1994

+
+

Greg Colvin proposed +to the C++ Standards Committee classes named auto_ptr and counted_ptr which were very +similar to what we now call scoped_ptr and shared_ptr. In one of the very few cases +where the Library Working Group’s recommendations were not followed by the full committee, +counted_ptr was rejected and surprising transfer-of-ownership semantics were added to auto_ptr.

+
+
+
+

October 1998

+
+

Beman Dawes proposed reviving the original semantics under the names safe_ptr and counted_ptr, +meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, +Dietmar Kühl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new class +names were finalized, it was decided that there was no need to exactly follow the std::auto_ptr +interface, and various function signatures and semantics were finalized.

+
+
+

Over the next three months, several implementations were considered for shared_ptr, and discussed +on the boost.org mailing list. The implementation questions revolved around +the reference count which must be kept, either attached to the pointed to object, or detached elsewhere. +Each of those variants have themselves two major variants:

+
+
+
    +
  • +

    Direct detached: the shared_ptr contains a pointer to the object, and a pointer to the count.

    +
  • +
  • +

    Indirect detached: the shared_ptr contains a pointer to a helper object, which in turn contains a pointer to the object and the count.

    +
  • +
  • +

    Embedded attached: the count is a member of the object pointed to.

    +
  • +
  • +

    Placement attached: the count is attached via operator new manipulations.

    +
  • +
+
+
+

Each implementation technique has advantages and disadvantages. We went so far as to run various timings +of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little +measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar Kühl +suggested an elegant partial template specialization technique to allow users to choose which implementation +they preferred, and that was also experimented with.

+
+
+

But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose +to supply only the direct implementation.

+
+
+
+

May 1999

+
+

In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.

+
+
+
+

September 1999

+
+

Luis Coelho provided shared_ptr::swap and shared_array::swap.

+
+
+
+

November 1999

+
+

Darin Adler provided operator ==, operator !=, and std::swap and std::less specializations for shared types.

+
+
+
+

May 2001

+
+

Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams, +Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.

+
+
+
+

January 2002

+
+

Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding +weak_ptr.

+
+
+
+

March 2003

+
+

Peter Dimov, Beman Dawes and Greg Colvin proposed shared_ptr +and weak_ptr for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was +accepted and eventually went on to become a part of the C++ standard in its 2011 iteration.

+
+
+
+

July 2007

+
+

Peter Dimov and Beman Dawes proposed a number of enhancements +to shared_ptr as it was entering the working paper that eventually became the C++11 standard.

+
+
+
+

November 2012

+
+

Glen Fernandes provided implementations of make_shared and allocate_shared for arrays. They achieve a single allocation +for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization +and no value initialization.

+
+
+

Peter Dimov aided this development by extending shared_ptr to support arrays via the syntax shared_ptr<T[]> and shared_ptr<T[N]>.

+
+
+
+

April 2013

+
+

Peter Dimov proposed the extension of shared_ptr to support +arrays for inclusion into the standard, and it was accepted.

+
+
+
+

February 2014

+
+

Glen Fernandes updated make_shared and allocate_shared to conform to the specification in C++ standard paper +N3870, and implemented make_unique for arrays and objects.

+
+
+

Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve C++ standard library defect 2070.

+
+
+
+

February 2017

+
+

Glen Fernandes rewrote allocate_shared and make_shared for arrays for a more optimal and more maintainable implementation.

+
+
+
+

June 2017

+
+

Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format.

+
+
+

Peter Dimov added atomic_shared_ptr and local_shared_ptr.

+
+
+
+

August 2019

+
+

Glen Fernandes implemented allocate_unique for scalars and arrays.

+
+
+
+
+
+

Appendix C: shared_array (deprecated)

+
+
+ + + + + +
+
Note
+
+This facility is deprecated because a shared_ptr to T[] or T[N] +is now available, and is superior in every regard. +
+
+
+

Description

+
+

The shared_array class template stores a pointer to a dynamically allocated +array. (Dynamically allocated array are allocated with the C++ new[] +expression.) The object pointed to is guaranteed to be deleted when the last +shared_array pointing to it is destroyed or reset.

+
+
+

Every shared_array meets the CopyConstructible and Assignable +requirements of the C++ Standard Library, and so can be used in standard +library containers. Comparison operators are supplied so that shared_array +works with the standard library’s associative containers.

+
+
+

Normally, a shared_array cannot correctly hold a pointer to an object that +has been allocated with the non-array form of new. See shared_ptr for that +usage.

+
+
+

Because the implementation uses reference counting, cycles of shared_array +instances will not be reclaimed. For example, if main holds a shared_array +to A, which directly or indirectly holds a shared_array back to A, the use +count of A will be 2. Destruction of the original shared_array will leave +A dangling with a use count of 1.

+
+
+

A shared_ptr to a std::vector is an alternative to a shared_array that +is a bit heavier duty but far more flexible.

+
+
+

The class template is parameterized on T, the type of the object pointed to. +shared_array and most of its member functions place no requirements on T; +it is allowed to be an incomplete type, or void. Member functions that do +place additional requirements (constructors, reset) are explicitly documented +below.

+
+
+
+

Synopsis

+
+
+
namespace boost {
+
+  template<class T> class shared_array {
+  public:
+    typedef T element_type;
+
+    explicit shared_array(T* p = 0);
+    template<class D> shared_array(T* p, D d);
+    shared_array(const shared_array& v) noexcept;
+
+    ~shared_array() noexcept;
+
+    shared_array& operator=(const shared_array& v) noexcept;
+
+    void reset(T* p = 0);
+    template<class D> void reset(T* p, D d);
+
+    T& operator[](std::ptrdiff_t n) const noexcept;
+    T* get() const noexcept;
+
+    bool unique() const noexcept;
+    long use_count() const noexcept;
+
+    explicit operator bool() const noexcept;
+
+    void swap(shared_array<T>& v) noexcept;
+  };
+
+  template<class T> bool
+    operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+  template<class T> bool
+    operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+  template<class T> bool
+    operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+
+  template<class T>
+    void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
+}
+
+
+
+
+

Members

+
+

element_type

+
+
+
typedef T element_type;
+
+
+
+
+
Type
+
+

Provides the type of the stored pointer.

+
+
+
+
+
+

Constructors

+
+
+
explicit shared_array(T* p = 0);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a shared_array, storing a copy of p, which must be a +pointer to an array that was allocated via a C++ new[] expression or be 0. +Afterwards, the use count is 1 (even if p == 0; see ~shared_array).

    +
    +
    Requires
    +
    +

    T is a complete type.

    +
    +
    Throws
    +
    +

    std::bad_alloc. If an exception is thrown, delete[] p is called.

    +
    +
    +
    +
  • +
+
+
+
+
template<class D> shared_array(T* p, D d);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a shared_array, storing a copy of p and of d. +Afterwards, the use count is 1. When the the time comes to delete the array +pointed to by p, the object d is used in the statement d(p).

    +
    +
    Requires
    +
    +
    +
  • +
  • +

    T is a complete type.

    +
  • +
  • +

    The copy constructor and destructor of D must not throw.

    +
  • +
  • +

    Invoking the object d with parameter p must not throw.

    +
    +
    +
    Throws
    +
    +

    std::bad_alloc. If an exception is thrown, d(p) is called.

    +
    +
    +
    +
  • +
+
+
+
+
shared_array(const shared_array& v) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a shared_array, as if by storing a copy of the pointer +stored in v. Afterwards, the use count for all copies is 1 more than the +initial use count.

    +
    +
    Requires
    +
    +

    T is a complete type.

    +
    +
    +
    +
  • +
+
+
+
+

Destructor

+
+
+
~shared_array() noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Decrements the use count. Then, if the use count is 0, deletes the +array pointed to by the stored pointer. Note that delete[] on a pointer with +a value of 0 is harmless.

    +
    +
    +
    +
  • +
+
+
+
+

Assignment

+
+
+
shared_array& operator=(const shared_array& v) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a new shared_array as described above, then replaces +this shared_array with the new one, destroying the replaced object.

    +
    +
    Requires
    +
    +

    T is a complete type.

    +
    +
    Returns
    +
    +

    *this.

    +
    +
    +
    +
  • +
+
+
+
+

reset

+
+
+
void reset(T* p = 0);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a new shared_array as described above, then replaces +this shared_array with the new one, destroying the replaced object.

    +
    +
    Requires
    +
    +

    T is a complete type.

    +
    +
    Throws
    +
    +

    std::bad_alloc. If an exception is thrown, delete[] p is called.

    +
    +
    +
    +
  • +
+
+
+
+
template<class D> void reset(T* p, D d);
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Constructs a new shared_array as described above, then replaces +this shared_array with the new one, destroying the replaced object.

    +
    +
    Requires
    +
    +
    +
  • +
  • +

    T is a complete type.

    +
  • +
  • +

    The copy constructor of D must not throw.

    +
    +
    +
    Throws
    +
    +

    std::bad_alloc. If an exception is thrown, d(p) is called.

    +
    +
    +
    +
  • +
+
+
+
+

Indexing

+
+
+
T& operator[](std::ptrdiff_t n) const noexcept;
+
+
+
+
+
Returns
+
+

A reference to element n of the array pointed to by the stored +pointer. Behavior is undefined and almost certainly undesirable if the stored +pointer is 0, or if n is less than 0 or is greater than or equal to the +number of elements in the array.

+
+
Requires
+
+

T is a complete type.

+
+
+
+
+
+

get

+
+
+
T* get() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The stored pointer.

    +
    +
    +
    +
    +

    # unique

    +
    +
  • +
+
+
+
+
bool unique() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    true if no other shared_array is sharing ownership of the +stored pointer, false otherwise.

    +
    +
    +
    +
  • +
+
+
+
+

use_count

+
+
+
long use_count() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The number of shared_array objects sharing ownership of the +stored pointer.

    +
    +
    +
    +
  • +
+
+
+
+

Conversions

+
+
+
explicit operator bool() const noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    get() != 0.

    +
    +
    Requires
    +
    +

    T is a complete type.

    +
    +
    +
    +
  • +
+
+
+
+

swap

+
+
+
void swap(shared_array<T>& b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Effects
    +
    +

    Exchanges the contents of the two smart pointers.

    +
    +
    +
    +
    +

    ## Free Functions

    +
    +
  • +
+
+
+
+

Comparison

+
+
+
template<class T> bool
+  operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+
+
+
+
+
template<class T> bool
+  operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+
+
+
+
+
template<class T> bool
+  operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    The result of comparing the stored pointers of the two smart +pointers.

    +
    +
    +
    +
  • +
+
+
+ + + + + +
+
Note
+
+The operator< overload is provided to define an ordering so that +shared_array objects can be used in associative containers such as +std::map. The implementation uses std::less<T*> to perform the comparison. +This ensures that the comparison is 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). +
+
+
+
+

swap

+
+
+
template<class T>
+  void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
+
+
+
+
    +
  • +

    +
    +
    +
    Returns
    +
    +

    a.swap(b).

    +
    +
    Requires
    +
    +

    T is a complete type.

    +
    +
    +
    +
  • +
+
+
+
+
+
+
+ +
+
+

This documentation is

+
+
+
    +
  • +

    Copyright 1999 Greg Colvin

    +
  • +
  • +

    Copyright 1999 Beman Dawes

    +
  • +
  • +

    Copyright 2002 Darin Adler

    +
  • +
  • +

    Copyright 2003-2017 Peter Dimov

    +
  • +
  • +

    Copyright 2005, 2006 Ion Gaztañaga

    +
  • +
  • +

    Copyright 2008 Frank Mori Hess

    +
  • +
  • +

    Copyright 2012-2017 Glen Fernandes

    +
  • +
  • +

    Copyright 2013 Andrey Semashev

    +
  • +
+
+
+

and is distributed under the Boost Software License, Version 1.0.

+
+
+
+
+ + + + \ No newline at end of file diff --git a/doc/smart_ptr/allocate_unique.adoc b/doc/smart_ptr/allocate_unique.adoc index b144e59..a8ef8ed 100644 --- a/doc/smart_ptr/allocate_unique.adoc +++ b/doc/smart_ptr/allocate_unique.adoc @@ -124,8 +124,8 @@ value `v`, or constructed from `args\...`, `allocate_unique` shall perform this initialization via the expression `std::allocator_traits::construct(a2, p, expr)` (where `_expr_` is `v` or `std::forward(args)\...)` respectively), `p` points to storage suitable -to hold an object of type `U`, and `a2` of type `A2` is a rebound copy `a` such -that its `value_type` is `U`. +to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound +copy of `a`. * When a (sub)object of non-array type `U` is specified to be default-initialized, `allocate_unique_noinit` shall perform this initialization via the expression `::new(p) U`, where `p` has type `void*` and points to @@ -134,7 +134,7 @@ storage suitable to hold an object of type `U`. value-initialized, `allocate_unique` shall perform this initialization via the expression `std::allocator_traits::construct(a2, p)`, where `p` points to storage suitable to hold an object of type `U` and `a2` of type `A2` is a -rebound copy of `a` such that its value_type is `U`. +potentially rebound copy of `a`. * Array elements are initialized in ascending order of their addresses. * When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized @@ -278,17 +278,15 @@ functions. [subs=+quotes] ``` -namespace boost { - template - class alloc_deleter { - public: - using pointer = `unspecified`; +template +class alloc_deleter { +public: + using pointer = `unspecified`; - explicit alloc_deleter(const A& a) noexcept; + explicit alloc_deleter(const A& a) noexcept; - void operator()(pointer p); - }; -} + void operator()(pointer p); +}; ``` ### Members diff --git a/doc/smart_ptr/make_local_shared.adoc b/doc/smart_ptr/make_local_shared.adoc index 3d586f7..3f0b0e1 100644 --- a/doc/smart_ptr/make_local_shared.adoc +++ b/doc/smart_ptr/make_local_shared.adoc @@ -27,25 +27,25 @@ are analogous to `make_shared` and `allocate_shared` for `shared_ptr`. [subs=+quotes] ``` namespace boost { - `// only if T is not an array type` + `// T is not an array` template local_shared_ptr make_local_shared(Args&&... args); template local_shared_ptr allocate_local_shared(const A& a, Args&&... args); - `// only if T is an array type of the form U[]` + `// T is an array of unknown bounds` template local_shared_ptr make_local_shared(std::size_t n); template local_shared_ptr allocate_local_shared(const A& a, std::size_t n); - `// only if T is an array type of the form U[N]` + `// T is an array of known bounds` template local_shared_ptr make_local_shared(); template local_shared_ptr allocate_local_shared(const A& a); - `// only if T is an array type of the form U[]` + `// T is an array of unknown bounds` template local_shared_ptr make_local_shared(std::size_t n, const remove_extent_t& v); @@ -53,20 +53,20 @@ namespace boost { local_shared_ptr allocate_local_shared(const A& a, std::size_t n, const remove_extent_t& v); - `// only if T is an array type of the form U[N]` + `// T is an array of known bounds` template local_shared_ptr make_local_shared(const remove_extent_t& v); template local_shared_ptr allocate_local_shared(const A& a, const remove_extent_t& v); - `// only if T is not an array type of the form U[]` + `// T is not an array of known bounds` template local_shared_ptr make_local_shared_noinit(); template local_shared_ptr allocate_local_shared_noinit(const A& a); - `// only if T is an array type of the form U[N]` + `// T is an array of unknown bounds` template local_shared_ptr make_local_shared_noinit(std::size_t n); template diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 375a91e..f88635e 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -55,43 +55,43 @@ types. [subs=+quotes] ``` namespace boost { - `// only if T is not an array type` + `// T is not an array` template shared_ptr make_shared(Args&&... args); template shared_ptr allocate_shared(const A& a, Args&&... args); - `// only if T is an array type of the form U[]` + `// T is an array of unknown bounds` template shared_ptr make_shared(std::size_t n); template shared_ptr allocate_shared(const A& a, std::size_t n); - `// only if T is an array type of the form U[N]` + `// T is an array of known bounds` template shared_ptr make_shared(); template shared_ptr allocate_shared(const A& a); - `// only if T is an array type of the form U[]` + `// T is an array of unknown bounds` template shared_ptr make_shared(std::size_t n, const remove_extent_t& v); template shared_ptr allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); - `// only if T is an array type of the form U[N]` + `// T is an array of known bounds` template shared_ptr make_shared(const remove_extent_t& v); template shared_ptr allocate_shared(const A& a, const remove_extent_t& v); - `// only if T is not an array type of the form U[]` + `// T is not an array of unknown bounds` template shared_ptr make_shared_noinit(); template shared_ptr allocate_shared_noinit(const A& a); - `// only if T is an array type of the form U[N]` + `// T is an array of unknown bounds` template shared_ptr make_shared_noinit(std::size_t n); template @@ -144,7 +144,7 @@ perform this initialization via the expression `std::allocator_traits::construct(a2, p, expr)` (where `_expr_` is `v` or `std::forward(args)\...)` respectively), `p` points to storage suitable to hold an object of type `U`, and `a2` of -type `A2` is a rebound copy `a` such that its `value_type` is `U`. +type `A2` is a potentially rebound copy `a`. * When a (sub)object of non-array type `U` is specified to be default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall perform this initialization via the expression `::new(p) U`, where @@ -158,7 +158,7 @@ storage suitable to hold an object of type `U`. value-initialized, `allocate_shared` shall perform this initialization via the expression `std::allocator_traits::construct(a2, p)`, where `p` points to storage suitable to hold an object of type `U` and `a2` of -type `A2` is a rebound copy of `a` such that its value_type is `U`. +type `A2` is a potentially rebound copy of `a`. * Array elements are initialized in ascending order of their addresses. * When the lifetime of the object managed by the return value ends, or when the initialization of an array element throws an exception, the initialized @@ -181,8 +181,7 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is not an array type. +Constraints:: `T` is not an array. Returns:: A `shared_ptr` to an object of type `T`, constructed from `args\...`. Examples:: @@ -200,10 +199,9 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[]`. +Constraints:: `T` is an array of unknown bounds. Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of -type `U`. +type `remove_extent_t`. Examples:: * `auto p = make_shared(1024);` * `auto p = make_shared(6);` @@ -219,10 +217,9 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[N]`. -Returns:: A `shared_ptr` to a sequence of `N` value-initialized objects of -type `U`. +Constraints:: `T` is an array of known bounds. +Returns:: A `shared_ptr` to a sequence of `extent_v` value-initialized +objects of type `remove_extent_t`. Examples:: * `auto p = make_shared();` * `auto p = make_shared();` @@ -238,10 +235,9 @@ template shared_ptr [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[]`. -Returns:: A `shared_ptr` to a sequence of `n` objects of type `U`, each -initialized to `v`. +Constraints:: `T` is an array of unknown bounds. +Returns:: A `shared_ptr` to a sequence of `n` objects of type +`remove_extent_t`, each initialized to `v`. Examples:: * `auto p = make_shared(1024, 1.0);` * `auto p = make_shared(6, {1.0, 0.0});` @@ -258,10 +254,9 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[N]`. -Returns:: A `shared_ptr` to a sequence of `N` objects of type `U`, each -initialized to `v`. +Constraints:: `T` is an array of known bounds. +Returns:: A `shared_ptr` to a sequence of `extent_v` objects of type +`remove_extent_t`, each initialized to `v`. Examples:: * `auto p = make_shared(1.0);` * `auto p = make_shared({1.0, 0.0});` @@ -278,10 +273,10 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is not an array type, or an array type of the `U[N]`. +Constraints:: `T` is not an array, or is an array of known bounds. Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a -sequence of `N` default-initialized objects of type `U`, respectively. +sequence of `extent_v` default-initialized objects of type +`remove_extent_t`, respectively. Example:: `auto p = make_shared_noinit();` ``` @@ -295,8 +290,7 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[]`. +Constraints:: `T` is an array of unknown bounds. Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects -of type `U`. +of type `remove_extent_t`. Example:: `auto p = make_shared_noinit(1024);` diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index feb569c..a260131 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -40,23 +40,23 @@ feature with `std::make_unique`. [subs=+quotes] ``` namespace boost { - `// only if T is not an array type` + `// T is not an array` template std::unique_ptr make_unique(Args&&... args); - `// only if T is not an array type` + `// T is not an array` template - std::unique_ptr make_unique(remove_reference_t&& v); + std::unique_ptr make_unique(type_identity_t&& v); - `// only if T is an array type of the form U[]` + `// T is an array of unknown bounds` template std::unique_ptr make_unique(std::size_t n); - `// only if T is not an array type` + `// T is not an array` template std::unique_ptr make_unique_noinit(); - `// only if T is an array type of the form U[]` + `// T is an array of unknown bounds` template std::unique_ptr make_unique_noinit(std::size_t n); } @@ -71,20 +71,18 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is not an array type. +Constraints:: `T` is not an array. Returns:: `std::unique_ptr(new T(std::forward(args)\...)`. Example:: `auto p = make_unique();` ``` template - std::unique_ptr make_unique(remove_reference_t&& v); + std::unique_ptr make_unique(type_identity_t&& v); ``` [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is not an array type. +Constraints:: `T` is not an array. Returns:: `std::unique_ptr(new T(std::move(v))`. Example:: `auto p = make_unique >({1, 2});` @@ -95,9 +93,8 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[]`. -Returns:: `std::unique_ptr(new U[n]())`. +Constraints:: `T` is an array of unknown bounds. +Returns:: `std::unique_ptr(new remove_extent_t[n]())`. Example:: `auto p = make_unique(1024);` ``` @@ -107,8 +104,7 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is not an array type. +Constraints:: `T` is not an array. Returns:: `std::unique_ptr(new T)`. Example:: `auto p = make_unique_noinit();` @@ -119,7 +115,6 @@ template [none] * {blank} + -Remarks:: These overloads shall only participate in overload resolution when -`T` is an array type of the form `U[]`. -Returns:: `std::unique_ptr(new U[n])`. +Constraints:: `T` is an array of unknown bounds. +Returns:: `std::unique_ptr(new remove_extent_t[n])`. Example:: `auto p = make_unique_noinit(1024);`