From a7341070f11b95099e91dae1ab845a46c60a90ae Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 3 Sep 2019 11:52:34 -0400 Subject: [PATCH] More documentation corrections --- doc/smart_ptr.html | 10918 --------------------------- doc/smart_ptr/allocate_unique.adoc | 8 +- doc/smart_ptr/make_shared.adoc | 2 +- 3 files changed, 5 insertions(+), 10923 deletions(-) delete mode 100644 doc/smart_ptr.html diff --git a/doc/smart_ptr.html b/doc/smart_ptr.html deleted file mode 100644 index 8647719..0000000 --- a/doc/smart_ptr.html +++ /dev/null @@ -1,10918 +0,0 @@ - - - - - - - - -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 a8ef8ed..c563673 100644 --- a/doc/smart_ptr/allocate_unique.adoc +++ b/doc/smart_ptr/allocate_unique.adoc @@ -64,12 +64,12 @@ namespace boost { `// T is an array of unknown bounds` template std::unique_ptr> - allocate_unique(const A& a, std::size_t n, const type_identity_t& v); + allocate_unique(const A& a, std::size_t n, const remove_extent_t& v); `// T is an array of known bounds` template std::unique_ptr[], alloc_deleter> - allocate_unique(const A& a, const type_identity_t& v); + allocate_unique(const A& a, const remove_extent_t& v); `// T is not an array` template @@ -202,7 +202,7 @@ Examples:: ``` template std::unique_ptr> - allocate_unique(const A& a, std::size_t n, const type_identity_t& v); + allocate_unique(const A& a, std::size_t n, const remove_extent_t& v); ``` [none] * {blank} @@ -218,7 +218,7 @@ Examples:: ``` template std::unique_ptr[], alloc_deleter> - allocate_unique(const A& a, const type_identity_t& v); + allocate_unique(const A& a, const remove_extent_t& v); ``` [none] * {blank} diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index f88635e..9f8c141 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -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 potentially rebound copy `a`. +type `A2` is a potentially rebound copy of `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