1//// 2Copyright 2017 Peter Dimov 3Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) 4 5Distributed under the Boost Software License, Version 1.0. 6 7See accompanying file LICENSE_1_0.txt or copy at 8http://www.boost.org/LICENSE_1_0.txt 9//// 10 11[#make_shared] 12# make_shared: Creating shared_ptr 13:toc: 14:toc-title: 15:idprefix: make_shared_ 16 17## Description 18 19The function templates `make_shared` and `allocate_shared` provide convenient, 20safe and efficient ways to create `shared_ptr` objects. 21 22## Rationale 23 24Consistent use of `shared_ptr` can eliminate the need to use an explicit 25`delete`, but alone it provides no support in avoiding explicit `new`. There 26were repeated requests from users for a factory function that creates an 27object of a given type and returns a `shared_ptr` to it. Besides convenience 28and style, such a function is also exception safe and considerably faster 29because it can use a single allocation for both the object and its 30corresponding control block, eliminating a significant portion of 31`shared_ptr` construction overhead. This eliminates one of the major 32efficiency complaints about `shared_ptr`. 33 34The family of overloaded function templates, `make_shared` and 35`allocate_shared`, were provided to address this need. `make_shared` uses the 36global `operator new` to allocate memory, whereas `allocate_shared` uses an 37user-supplied allocator, allowing finer control. 38 39The rationale for choosing the name `make_shared` is that the expression 40`make_shared<Widget>()` can be read aloud and conveys the intended meaning. 41 42Originally the Boost function templates `allocate_shared` and `make_shared` 43were provided for scalar objects only. There was a need to have efficient 44allocation of array objects. One criticism of class template `shared_array` 45was always the lack of a utility like `make_shared` that uses only a single 46allocation. When `shared_ptr` was enhanced to support array types, additional 47overloads of `allocate_shared` and `make_shared` were provided for array 48types. 49 50## Synopsis 51 52`make_shared` and `allocate_shared` are defined in 53`<boost/smart_ptr/make_shared.hpp>`. 54 55[subs=+quotes] 56``` 57namespace boost { 58 `// T is not an array` 59 template<class T, class... Args> 60 shared_ptr<T> make_shared(Args&&... args); 61 template<class T, class A, class... Args> 62 shared_ptr<T> allocate_shared(const A& a, Args&&... args); 63 64 `// T is an array of unknown bounds` 65 template<class T> 66 shared_ptr<T> make_shared(std::size_t n); 67 template<class T, class A> 68 shared_ptr<T> allocate_shared(const A& a, std::size_t n); 69 70 `// T is an array of known bounds` 71 template<class T> 72 shared_ptr<T> make_shared(); 73 template<class T, class A> 74 shared_ptr<T> allocate_shared(const A& a); 75 76 `// T is an array of unknown bounds` 77 template<class T> shared_ptr<T> 78 make_shared(std::size_t n, const remove_extent_t<T>& v); 79 template<class T, class A> shared_ptr<T> 80 allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v); 81 82 `// T is an array of known bounds` 83 template<class T> 84 shared_ptr<T> make_shared(const remove_extent_t<T>& v); 85 template<class T, class A> 86 shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v); 87 88 `// T is not an array of unknown bounds` 89 template<class T> 90 shared_ptr<T> make_shared_noinit(); 91 template<class T, class A> 92 shared_ptr<T> allocate_shared_noinit(const A& a); 93 94 `// T is an array of unknown bounds` 95 template<class T> 96 shared_ptr<T> make_shared_noinit(std::size_t n); 97 template<class T, class A> 98 shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n); 99} 100``` 101 102## Common Requirements 103 104The common requirements that apply to all `make_shared` and `allocate_shared` 105overloads, unless specified otherwise, are described below. 106 107Requires:: `A` shall be an _allocator_. The copy constructor and destructor 108of `A` shall not throw exceptions. 109 110Effects:: Allocates memory for an object of type `T` or `n` objects of `U` 111(if `T` is an array type of the form `U[]` and `n` is determined by 112arguments, as specified by the concrete overload). The object is initialized 113from arguments as specified by the concrete overload. Uses a rebound copy of 114`a` (for an unspecified `value_type`) to allocate memory. If an exception is 115thrown, the functions have no effect. 116 117Returns:: A `shared_ptr` instance that stores and owns the address of the 118newly constructed object. 119 120Postconditions:: `r.get() != 0` and `r.use_count() == 1`, where `r` 121is the return value. 122 123Throws:: `std::bad_alloc`, an exception thrown from `A::allocate`, or from the 124initialization of the object. 125 126Remarks:: 127* Performs no more than one memory allocation. This provides efficiency 128equivalent to an intrusive smart pointer. 129* When an object of an array type is specified to be initialized to a value of 130the same type `v`, this shall be interpreted to mean that each array element 131of the object is initialized to the corresponding element from `v`. 132* When an object of an array type is specified to be value-initialized, this 133shall be interpreted to mean that each array element of the object is 134value-initialized. 135* When a (sub)object of non-array type `U` is specified to be initialized to 136a value `v`, or constructed from `args\...`, `make_shared` shall perform 137this initialization via the expression `::new(p) U(expr)` (where 138`_expr_` is `v` or `std::forward<Args>(args)\...)` respectively) and `p` 139has type `void*` and points to storage suitable to hold an object of type 140`U`. 141* When a (sub)object of non-array type `U` is specified to be initialized to 142a value `v`, or constructed from `args\...`, `allocate_shared` shall 143perform this initialization via the expression 144`std::allocator_traits<A2>::construct(a2, p, expr)` (where 145`_expr_` is `v` or `std::forward<Args>(args)\...)` respectively), `p` 146points to storage suitable to hold an object of type `U`, and `a2` of 147type `A2` is a potentially rebound copy of `a`. 148* When a (sub)object of non-array type `U` is specified to be 149default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall 150perform this initialization via the expression `::new(p) U`, where 151`p` has type `void*` and points to storage suitable to hold an object of 152type `U`. 153* When a (sub)object of non-array type `U` is specified to be 154value-initialized, `make_shared` shall perform this initialization via the 155expression `::new(p) U()`, where `p` has type `void*` and points to 156storage suitable to hold an object of type `U`. 157* When a (sub)object of non-array type `U` is specified to be 158value-initialized, `allocate_shared` shall perform this initialization via the 159expression `std::allocator_traits<A2>::construct(a2, p)`, where 160`p` points to storage suitable to hold an object of type `U` and `a2` of 161type `A2` is a potentially rebound copy of `a`. 162* Array elements are initialized in ascending order of their addresses. 163* When the lifetime of the object managed by the return value ends, or when 164the initialization of an array element throws an exception, the initialized 165elements should be destroyed in the reverse order of their construction. 166 167NOTE: These functions will typically allocate more memory than the total size 168of the element objects to allow for internal bookkeeping structures such as 169the reference counts. 170 171## Free Functions 172 173``` 174template<class T, class... Args> 175 shared_ptr<T> make_shared(Args&&... args); 176``` 177``` 178template<class T, class A, class... Args> 179 shared_ptr<T> allocate_shared(const A& a, Args&&... args); 180``` 181[none] 182* {blank} 183+ 184Constraints:: `T` is not an array. 185Returns:: A `shared_ptr` to an object of type `T`, constructed from 186`args\...`. 187Examples:: 188* `auto p = make_shared<int>();` 189* `auto p = make_shared<std::vector<int> >(16, 1);` 190 191``` 192template<class T> 193 shared_ptr<T> make_shared(std::size_t n); 194``` 195``` 196template<class T, class A> 197 shared_ptr<T> allocate_shared(const A& a, std::size_t n); 198``` 199[none] 200* {blank} 201+ 202Constraints:: `T` is an array of unknown bounds. 203Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of 204type `remove_extent_t<T>`. 205Examples:: 206* `auto p = make_shared<double[]>(1024);` 207* `auto p = make_shared<double[][2][2]>(6);` 208 209``` 210template<class T> 211 shared_ptr<T> make_shared(); 212``` 213``` 214template<class T, class A> 215 shared_ptr<T> allocate_shared(const A& a); 216``` 217[none] 218* {blank} 219+ 220Constraints:: `T` is an array of known bounds. 221Returns:: A `shared_ptr` to a sequence of `extent_v<T>` value-initialized 222objects of type `remove_extent_t<T>`. 223Examples:: 224* `auto p = make_shared<double[1024]>();` 225* `auto p = make_shared<double[6][2][2]>();` 226 227``` 228template<class T> shared_ptr<T> 229 make_shared(std::size_t n, const remove_extent_t<T>& v); 230``` 231``` 232template<class T, class A> shared_ptr<T> 233 allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v); 234``` 235[none] 236* {blank} 237+ 238Constraints:: `T` is an array of unknown bounds. 239Returns:: A `shared_ptr` to a sequence of `n` objects of type 240`remove_extent_t<T>`, each initialized to `v`. 241Examples:: 242* `auto p = make_shared<double[]>(1024, 1.0);` 243* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});` 244* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});` 245 246``` 247template<class T> 248 shared_ptr<T> make_shared(const remove_extent_t<T>& v); 249``` 250``` 251template<class T, class A> 252 shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v); 253``` 254[none] 255* {blank} 256+ 257Constraints:: `T` is an array of known bounds. 258Returns:: A `shared_ptr` to a sequence of `extent_v<T>` objects of type 259`remove_extent_t<T>`, each initialized to `v`. 260Examples:: 261* `auto p = make_shared<double[1024]>(1.0);` 262* `auto p = make_shared<double[6][2]>({1.0, 0.0});` 263* `auto p = make_shared<std::vector<int>[4]>({1, 2});` 264 265``` 266template<class T> 267 shared_ptr<T> make_shared_noinit(); 268``` 269``` 270template<class T, class A> 271 shared_ptr<T> allocate_shared_noinit(const A& a); 272``` 273[none] 274* {blank} 275+ 276Constraints:: `T` is not an array, or is an array of known bounds. 277Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a 278sequence of `extent_v<T>` default-initialized objects of type 279`remove_extent_t<T>`, respectively. 280Example:: `auto p = make_shared_noinit<double[1024]>();` 281 282``` 283template<class T> 284 shared_ptr<T> make_shared_noinit(std::size_t n); 285``` 286``` 287template<class T, class A> 288 shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n); 289``` 290[none] 291* {blank} 292+ 293Constraints:: `T` is an array of unknown bounds. 294Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects 295of type `remove_extent_t<T>`. 296Example:: `auto p = make_shared_noinit<double[]>(1024);` 297