1//// 2Copyright 1999 Greg Colvin and Beman Dawes 3Copyright 2002 Darin Adler 4Copyright 2002-2005, 2017 Peter Dimov 5 6Distributed under the Boost Software License, Version 1.0. 7 8See accompanying file LICENSE_1_0.txt or copy at 9http://www.boost.org/LICENSE_1_0.txt 10//// 11 12[#weak_ptr] 13# weak_ptr: Non-owning Observer 14:toc: 15:toc-title: 16:idprefix: weak_ptr_ 17 18## Description 19 20The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`. 21To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking 22`weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the 23object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted 24object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will 25return an empty `shared_ptr`. 26 27Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so 28can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard 29library's associative containers. 30 31`weak_ptr` operations never throw exceptions. 32 33The class template is parameterized on `T`, the type of the object pointed to. 34 35Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is 36often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined 37behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent 38piece of code: 39 40``` 41shared_ptr<int> p(new int(5)); 42weak_ptr<int> q(p); 43 44// some time later 45 46if(int * r = q.get()) 47{ 48 // use *r 49} 50``` 51 52Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer. 53 54The solution to this problem is to create a temporary `shared_ptr` from `q`: 55 56``` 57shared_ptr<int> p(new int(5)); 58weak_ptr<int> q(p); 59 60// some time later 61 62if(shared_ptr<int> r = q.lock()) 63{ 64 // use *r 65} 66``` 67 68Now `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 69`r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction. 70 71## Synopsis 72 73`weak_ptr` is defined in `<boost/smart_ptr/weak_ptr.hpp>`. 74 75``` 76namespace boost { 77 78 template<class T> class weak_ptr { 79 public: 80 81 typedef /*see below*/ element_type; 82 83 weak_ptr() noexcept; 84 85 template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept; 86 weak_ptr(weak_ptr const & r) noexcept; 87 template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept; 88 89 weak_ptr(weak_ptr && r) noexcept; 90 91 template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept; 92 template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept; 93 template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept; 94 95 ~weak_ptr() noexcept; 96 97 weak_ptr & operator=(weak_ptr const & r) noexcept; 98 weak_ptr & operator=(weak_ptr && r) noexcept; 99 template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept; 100 template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept; 101 102 long use_count() const noexcept; 103 bool expired() const noexcept; 104 105 bool empty() const noexcept; 106 107 shared_ptr<T> lock() const noexcept; 108 109 void reset() noexcept; 110 111 void swap(weak_ptr<T> & b) noexcept; 112 113 template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept; 114 template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept; 115 116 template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept; 117 template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept; 118 119 std::size_t owner_hash_value() const noexcept; 120 }; 121 122 template<class T, class U> 123 bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept; 124 125 template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept; 126} 127``` 128 129## Members 130 131### element_type 132``` 133typedef ... element_type; 134``` 135`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. 136 137### constructors 138``` 139weak_ptr() noexcept; 140``` 141[none] 142* {blank} 143+ 144Effects:: Constructs an empty `weak_ptr`. 145Postconditions:: `use_count() == 0`. 146 147``` 148template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept; 149``` 150``` 151weak_ptr(weak_ptr const & r) noexcept; 152``` 153``` 154template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept; 155``` 156[none] 157* {blank} 158+ 159Effects:: 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`. 160Postconditions:: `use_count() == r.use_count()`. 161 162``` 163weak_ptr(weak_ptr && r) noexcept; 164``` 165[none] 166* {blank} 167+ 168Effects:: Constructs a `weak_ptr` that has the value `r` held. 169Postconditions:: `r` is empty. 170 171### aliasing constructors 172``` 173template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept; 174``` 175``` 176template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept; 177``` 178``` 179template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept; 180``` 181Effects:: Constructs a `weak_ptr` from `r` as if by using the corresponding converting/copy/move constructor, but stores `p` instead. 182Postconditions:: `use_count() == r.use_count()`. When `!expired()`, `shared_ptr<T>(*this).get() == p`. 183 184NOTE: These constructors are an extension, not present in `std::weak_ptr`. 185 186### destructor 187``` 188~weak_ptr() noexcept; 189``` 190[none] 191* {blank} 192+ 193Effects:: 194 Destroys this `weak_ptr` but has no effect on the object its stored pointer points to. 195 196### assignment 197``` 198weak_ptr & operator=(weak_ptr const & r) noexcept; 199``` 200``` 201weak_ptr & operator=(weak_ptr && r) noexcept; 202``` 203``` 204template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept; 205``` 206``` 207template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept; 208``` 209[none] 210* {blank} 211+ 212Effects:: Equivalent to `weak_ptr(r).swap(*this)`. 213 214NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. 215 216### use_count 217``` 218long use_count() const noexcept; 219``` 220[none] 221* {blank} 222+ 223Returns:: 224 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`. 225 226### expired 227``` 228bool expired() const noexcept; 229``` 230[none] 231* {blank} 232+ 233Returns:: 234 `use_count() == 0`. 235 236### empty 237``` 238bool empty() const noexcept; 239``` 240[none] 241* {blank} 242+ 243Returns:: `true` when `*this` is empty, `false` otherwise. 244 245NOTE: This function is an extension, not present in `std::weak_ptr`. 246 247### lock 248``` 249shared_ptr<T> lock() const noexcept; 250``` 251[none] 252* {blank} 253+ 254Returns:: 255 `expired()? shared_ptr<T>(): shared_ptr<T>(*this)`. 256 257### reset 258``` 259void reset() noexcept; 260``` 261[none] 262* {blank} 263+ 264Effects:: 265 Equivalent to `weak_ptr().swap(*this)`. 266 267### swap 268``` 269void swap(weak_ptr & b) noexcept; 270``` 271[none] 272* {blank} 273+ 274Effects:: 275 Exchanges the contents of the two smart pointers. 276 277### owner_before 278``` 279template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept; 280``` 281``` 282template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept; 283``` 284[none] 285* {blank} 286+ 287Returns:: 288 See the description of `operator<`. 289 290### owner_equals 291``` 292template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept; 293``` 294``` 295template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept; 296``` 297[none] 298* {blank} 299+ 300Returns:: 301 `true` if and only if `*this` and `r` share ownership or are both empty. 302 303### owner_hash_value 304``` 305std::size_t owner_hash_value() const noexcept; 306``` 307[none] 308* {blank} 309+ 310Returns:: 311 An unspecified hash value such that two instances that share ownership 312 have the same hash value. 313 314## Free Functions 315 316### comparison 317``` 318template<class T, class U> 319 bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept; 320``` 321[none] 322* {blank} 323+ 324Returns:: An unspecified value such that 325- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; 326- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances 327 are equivalent if and only if they share ownership or are both empty. 328 329NOTE: Allows `weak_ptr` objects to be used as keys in associative containers. 330 331### swap 332``` 333template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept; 334``` 335[none] 336* {blank} 337+ 338Effects:: 339 Equivalent to `a.swap(b)`. 340 341## Frequently Asked Questions 342 343[qanda] 344Can an object create a weak_ptr to itself in its constructor?:: 345 346 No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no 347 `shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`, 348 it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire. 349+ 350The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`: 351+ 352``` 353class X 354{ 355private: 356 357 X(); 358 359public: 360 361 static shared_ptr<X> create() 362 { 363 shared_ptr<X> px(new X); 364 // create weak pointers from px here 365 return px; 366 } 367}; 368``` 369