• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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