blob: d51eaa1add910c4d15cd18df8e27aa892b5ef641 [file] [log] [blame]
Brian Silverman355f11d2018-08-04 23:57:00 -07001////
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 ~weak_ptr() noexcept;
92
93 weak_ptr & operator=(weak_ptr const & r) noexcept;
94 weak_ptr & operator=(weak_ptr && r) noexcept;
95 template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
96 template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
97
98 long use_count() const noexcept;
99 bool expired() const noexcept;
100
101 shared_ptr<T> lock() const noexcept;
102
103 void reset() noexcept;
104
105 void swap(weak_ptr<T> & b) noexcept;
106
107 template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
108 template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
109 };
110
111 template<class T, class U>
112 bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
113
114 template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
115}
116```
117
118## Members
119
120### element_type
121```
122typedef ... element_type;
123```
124`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`.
125
126### constructors
127```
128weak_ptr() noexcept;
129```
130[none]
131* {blank}
132+
133Effects:: Constructs an empty `weak_ptr`.
134Postconditions:: `use_count() == 0`.
135
136```
137template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
138```
139```
140weak_ptr(weak_ptr const & r) noexcept;
141```
142```
143template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
144```
145[none]
146* {blank}
147+
148Effects:: 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`.
149Postconditions:: `use_count() == r.use_count()`.
150
151```
152weak_ptr(weak_ptr && r) noexcept;
153```
154[none]
155* {blank}
156+
157Effects:: Constructs a `weak_ptr` that has the value `r` held.
158Postconditions:: `r` is empty.
159
160### destructor
161```
162~weak_ptr() noexcept;
163```
164[none]
165* {blank}
166+
167Effects:: Destroys this `weak_ptr` but has no effect on the object its stored pointer points to.
168
169### assignment
170```
171weak_ptr & operator=(weak_ptr const & r) noexcept;
172```
173```
174weak_ptr & operator=(weak_ptr && r) noexcept;
175```
176```
177template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
178```
179```
180template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
181```
182[none]
183* {blank}
184+
185Effects:: Equivalent to `weak_ptr(r).swap(*this)`.
186
187NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.
188
189### use_count
190```
191long use_count() const noexcept;
192```
193[none]
194* {blank}
195+
196Returns:: 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`.
197
198### expired
199```
200bool expired() const noexcept;
201```
202[none]
203* {blank}
204+
205Returns:: `use_count() == 0`.
206
207### lock
208```
209shared_ptr<T> lock() const noexcept;
210```
211[none]
212* {blank}
213+
214Returns:: `expired()? shared_ptr<T>(): shared_ptr<T>(*this)`.
215
216### reset
217```
218void reset() noexcept;
219```
220[none]
221* {blank}
222+
223Effects:: Equivalent to `weak_ptr().swap(*this)`.
224
225### swap
226```
227void swap(weak_ptr & b) noexcept;
228```
229[none]
230* {blank}
231+
232Effects:: Exchanges the contents of the two smart pointers.
233
234```
235template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
236```
237```
238template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
239```
240[none]
241* {blank}
242+
243Returns:: See the description of `operator<`.
244
245## Free Functions
246
247### comparison
248```
249template<class T, class U>
250 bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
251```
252[none]
253* {blank}
254+
255Returns:: An unspecified value such that
256- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;
257- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances
258 are equivalent if and only if they share ownership or are both empty.
259
260NOTE: Allows `weak_ptr` objects to be used as keys in associative containers.
261
262### swap
263```
264template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
265```
266[none]
267* {blank}
268+
269Effects:: Equivalent to `a.swap(b)`.
270
271## Frequently Asked Questions
272
273[qanda]
274Can an object create a weak_ptr to itself in its constructor?::
275
276 No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no
277 `shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`,
278 it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire.
279+
280The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`:
281+
282```
283class X
284{
285private:
286
287 X();
288
289public:
290
291 static shared_ptr<X> create()
292 {
293 shared_ptr<X> px(new X);
294 // create weak pointers from px here
295 return px;
296 }
297};
298```