Brian Silverman | 355f11d | 2018-08-04 23:57:00 -0700 | [diff] [blame^] | 1 | //// |
| 2 | Copyright 2017 Peter Dimov |
| 3 | |
| 4 | Distributed under the Boost Software License, Version 1.0. |
| 5 | |
| 6 | See accompanying file LICENSE_1_0.txt or copy at |
| 7 | http://www.boost.org/LICENSE_1_0.txt |
| 8 | //// |
| 9 | |
| 10 | [[shared_array]] |
| 11 | [appendix] |
| 12 | # shared_array (deprecated) |
| 13 | :toc: |
| 14 | :toc-title: |
| 15 | :idprefix: shared_array_ |
| 16 | |
| 17 | NOTE: This facility is deprecated because a `shared_ptr` to `T[]` or `T[N]` |
| 18 | is now available, and is superior in every regard. |
| 19 | |
| 20 | ## Description |
| 21 | |
| 22 | The `shared_array` class template stores a pointer to a dynamically allocated |
| 23 | array. (Dynamically allocated array are allocated with the C++ `new[]` |
| 24 | expression.) The object pointed to is guaranteed to be deleted when the last |
| 25 | `shared_array` pointing to it is destroyed or reset. |
| 26 | |
| 27 | Every `shared_array` meets the _CopyConstructible_ and _Assignable_ |
| 28 | requirements of the {cpp} Standard Library, and so can be used in standard |
| 29 | library containers. Comparison operators are supplied so that shared_array |
| 30 | works with the standard library's associative containers. |
| 31 | |
| 32 | Normally, a `shared_array` cannot correctly hold a pointer to an object that |
| 33 | has been allocated with the non-array form of `new`. See `shared_ptr` for that |
| 34 | usage. |
| 35 | |
| 36 | Because the implementation uses reference counting, cycles of `shared_array` |
| 37 | instances will not be reclaimed. For example, if `main` holds a shared_array |
| 38 | to `A`, which directly or indirectly holds a shared_array back to `A`, the use |
| 39 | count of `A` will be 2. Destruction of the original `shared_array` will leave |
| 40 | `A` dangling with a use count of 1. |
| 41 | |
| 42 | A `shared_ptr` to a `std::vector` is an alternative to a `shared_array` that |
| 43 | is a bit heavier duty but far more flexible. |
| 44 | |
| 45 | The class template is parameterized on `T`, the type of the object pointed to. |
| 46 | `shared_array` and most of its member functions place no requirements on `T`; |
| 47 | it is allowed to be an incomplete type, or `void`. Member functions that do |
| 48 | place additional requirements (constructors, reset) are explicitly documented |
| 49 | below. |
| 50 | |
| 51 | ## Synopsis |
| 52 | |
| 53 | ``` |
| 54 | namespace boost { |
| 55 | |
| 56 | template<class T> class shared_array { |
| 57 | public: |
| 58 | typedef T element_type; |
| 59 | |
| 60 | explicit shared_array(T* p = 0); |
| 61 | template<class D> shared_array(T* p, D d); |
| 62 | shared_array(const shared_array& v) noexcept; |
| 63 | |
| 64 | ~shared_array() noexcept; |
| 65 | |
| 66 | shared_array& operator=(const shared_array& v) noexcept; |
| 67 | |
| 68 | void reset(T* p = 0); |
| 69 | template<class D> void reset(T* p, D d); |
| 70 | |
| 71 | T& operator[](std::ptrdiff_t n) const noexcept; |
| 72 | T* get() const noexcept; |
| 73 | |
| 74 | bool unique() const noexcept; |
| 75 | long use_count() const noexcept; |
| 76 | |
| 77 | explicit operator bool() const noexcept; |
| 78 | |
| 79 | void swap(shared_array<T>& v) noexcept; |
| 80 | }; |
| 81 | |
| 82 | template<class T> bool |
| 83 | operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept; |
| 84 | template<class T> bool |
| 85 | operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept; |
| 86 | template<class T> bool |
| 87 | operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept; |
| 88 | |
| 89 | template<class T> |
| 90 | void swap(shared_array<T>& a, shared_array<T>& b) noexcept; |
| 91 | } |
| 92 | ``` |
| 93 | |
| 94 | ## Members |
| 95 | |
| 96 | ### element_type |
| 97 | |
| 98 | ``` |
| 99 | typedef T element_type; |
| 100 | ``` |
| 101 | Type:: Provides the type of the stored pointer. |
| 102 | |
| 103 | ### Constructors |
| 104 | |
| 105 | ``` |
| 106 | explicit shared_array(T* p = 0); |
| 107 | ``` |
| 108 | :: |
| 109 | Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a |
| 110 | pointer to an array that was allocated via a C++ `new[]` expression or be 0. |
| 111 | Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`). |
| 112 | Requires::: `T` is a complete type. |
| 113 | Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. |
| 114 | |
| 115 | ``` |
| 116 | template<class D> shared_array(T* p, D d); |
| 117 | ``` |
| 118 | :: |
| 119 | Effects::: Constructs a `shared_array`, storing a copy of `p` and of `d`. |
| 120 | Afterwards, the use count is 1. When the the time comes to delete the array |
| 121 | pointed to by `p`, the object `d` is used in the statement `d(p)`. |
| 122 | Requires::: |
| 123 | * `T` is a complete type. |
| 124 | * The copy constructor and destructor of `D` must not throw. |
| 125 | * Invoking the object `d` with parameter `p` must not throw. |
| 126 | Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. |
| 127 | |
| 128 | ``` |
| 129 | shared_array(const shared_array& v) noexcept; |
| 130 | ``` |
| 131 | :: |
| 132 | Effects::: Constructs a `shared_array`, as if by storing a copy of the pointer |
| 133 | stored in `v`. Afterwards, the use count for all copies is 1 more than the |
| 134 | initial use count. |
| 135 | Requires::: `T` is a complete type. |
| 136 | |
| 137 | ### Destructor |
| 138 | |
| 139 | ``` |
| 140 | ~shared_array() noexcept; |
| 141 | ``` |
| 142 | :: |
| 143 | Effects::: Decrements the use count. Then, if the use count is 0, deletes the |
| 144 | array pointed to by the stored pointer. Note that `delete[]` on a pointer with |
| 145 | a value of 0 is harmless. |
| 146 | |
| 147 | ### Assignment |
| 148 | |
| 149 | ``` |
| 150 | shared_array& operator=(const shared_array& v) noexcept; |
| 151 | ``` |
| 152 | :: |
| 153 | Effects::: Constructs a new `shared_array` as described above, then replaces |
| 154 | this `shared_array` with the new one, destroying the replaced object. |
| 155 | Requires::: `T` is a complete type. |
| 156 | Returns::: `*this`. |
| 157 | |
| 158 | ### reset |
| 159 | |
| 160 | ``` |
| 161 | void reset(T* p = 0); |
| 162 | ``` |
| 163 | :: |
| 164 | Effects::: Constructs a new `shared_array` as described above, then replaces |
| 165 | this `shared_array` with the new one, destroying the replaced object. |
| 166 | Requires::: `T` is a complete type. |
| 167 | Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. |
| 168 | |
| 169 | ``` |
| 170 | template<class D> void reset(T* p, D d); |
| 171 | ``` |
| 172 | :: |
| 173 | Effects::: Constructs a new `shared_array` as described above, then replaces |
| 174 | this `shared_array` with the new one, destroying the replaced object. |
| 175 | Requires::: |
| 176 | * `T` is a complete type. |
| 177 | * The copy constructor of `D` must not throw. |
| 178 | Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. |
| 179 | |
| 180 | ### Indexing |
| 181 | |
| 182 | ``` |
| 183 | T& operator[](std::ptrdiff_t n) const noexcept; |
| 184 | ``` |
| 185 | Returns::: A reference to element `n` of the array pointed to by the stored |
| 186 | pointer. Behavior is undefined and almost certainly undesirable if the stored |
| 187 | pointer is 0, or if `n` is less than 0 or is greater than or equal to the |
| 188 | number of elements in the array. |
| 189 | Requires::: `T` is a complete type. |
| 190 | |
| 191 | ### get |
| 192 | |
| 193 | ``` |
| 194 | T* get() const noexcept; |
| 195 | ``` |
| 196 | :: |
| 197 | Returns::: The stored pointer. |
| 198 | |
| 199 | ### unique |
| 200 | |
| 201 | ``` |
| 202 | bool unique() const noexcept; |
| 203 | ``` |
| 204 | :: |
| 205 | Returns::: `true` if no other `shared_array` is sharing ownership of the |
| 206 | stored pointer, `false` otherwise. |
| 207 | |
| 208 | ### use_count |
| 209 | |
| 210 | ``` |
| 211 | long use_count() const noexcept; |
| 212 | ``` |
| 213 | :: |
| 214 | Returns::: The number of `shared_array` objects sharing ownership of the |
| 215 | stored pointer. |
| 216 | |
| 217 | ### Conversions |
| 218 | |
| 219 | ``` |
| 220 | explicit operator bool() const noexcept; |
| 221 | ``` |
| 222 | :: |
| 223 | Returns::: `get() != 0`. |
| 224 | Requires::: `T` is a complete type. |
| 225 | |
| 226 | ### swap |
| 227 | |
| 228 | ``` |
| 229 | void swap(shared_array<T>& b) noexcept; |
| 230 | ``` |
| 231 | :: |
| 232 | Effects::: Exchanges the contents of the two smart pointers. |
| 233 | |
| 234 | ## Free Functions |
| 235 | |
| 236 | ### Comparison |
| 237 | |
| 238 | ``` |
| 239 | template<class T> bool |
| 240 | operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept; |
| 241 | ``` |
| 242 | ``` |
| 243 | template<class T> bool |
| 244 | operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept; |
| 245 | ``` |
| 246 | ``` |
| 247 | template<class T> bool |
| 248 | operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept; |
| 249 | ``` |
| 250 | :: |
| 251 | Returns::: The result of comparing the stored pointers of the two smart |
| 252 | pointers. |
| 253 | |
| 254 | NOTE: The `operator<` overload is provided to define an ordering so that |
| 255 | `shared_array` objects can be used in associative containers such as |
| 256 | `std::map`. The implementation uses `std::less<T*>` to perform the comparison. |
| 257 | This ensures that the comparison is handled correctly, since the standard |
| 258 | mandates that relational operations on pointers are unspecified (5.9 |
| 259 | [expr.rel] paragraph 2) but `std::less` on pointers is well-defined (20.3.3 |
| 260 | [lib.comparisons] paragraph 8). |
| 261 | |
| 262 | ### swap |
| 263 | |
| 264 | ``` |
| 265 | template<class T> |
| 266 | void swap(shared_array<T>& a, shared_array<T>& b) noexcept; |
| 267 | ``` |
| 268 | :: |
| 269 | Returns::: `a.swap(b)`. |
| 270 | Requires::: `T` is a complete type. |