forked from boostorg/smart_ptr
Update make_shared documentation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
////
|
||||
Copyright 2017 Peter Dimov
|
||||
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
@@ -13,3 +14,258 @@ http://www.boost.org/LICENSE_1_0.txt
|
||||
:toc-title:
|
||||
:idprefix: make_shared_
|
||||
|
||||
## 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>`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
namespace boost {
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared();
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a);
|
||||
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(std::size_t n, _see below_ v);
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, std::size_t n, _see below_ v);
|
||||
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(_see below_ v);
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, _see below_ v);
|
||||
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit();
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a);
|
||||
|
||||
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);
|
||||
}
|
||||
```
|
||||
|
||||
## Free Functions
|
||||
|
||||
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:: 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 rebound copy `a` such that its `value_type` is `_U_`.
|
||||
* 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 rebound copy of `a` such that its value_type is `_U_`.
|
||||
* 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.
|
||||
|
||||
```
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type.
|
||||
Returns::: A `shared_ptr` to an object of type `T`, constructed from
|
||||
`args$$...$$`.
|
||||
|
||||
```
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `__U__[]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of
|
||||
type `_U_`.
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared();
|
||||
```
|
||||
::
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `__U__[__N__]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `_N_` value-initialized objects of
|
||||
type `_U_`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(std::size_t n, _see below_ v);
|
||||
```
|
||||
::
|
||||
[subs=+quotes]
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, std::size_t n, _see below_ v);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `__U__[]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `n` objects of type `_U_`, each
|
||||
initialized to `v`.
|
||||
|
||||
[subs=+quotes]
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared(_see below_ v);
|
||||
```
|
||||
::
|
||||
[subs=+quotes]
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a, _see below_ v);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `__U__[__N__]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `_N_` objects of type `_U_`, each
|
||||
initialized to `v`.
|
||||
|
||||
```
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit();
|
||||
```
|
||||
::
|
||||
```
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type, or an array type of the `__U__[__N__]`.
|
||||
Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a
|
||||
sequence of `_N_` default-initialized objects of type `_U_`, respectively.
|
||||
|
||||
```
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `__U__[]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects
|
||||
of type `_U_`.
|
||||
|
Reference in New Issue
Block a user