• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1////
2Copyright 2017 Peter Dimov
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10[#scoped_ptr]
11# scoped_ptr: Scoped Object Ownership
12:toc:
13:toc-title:
14:idprefix: scoped_ptr_
15
16## Description
17
18The `scoped_ptr` class template stores a pointer to a dynamically allocated object.
19(Dynamically allocated objects are allocated with the {cpp} `new` expression.) The
20object pointed to is guaranteed to be deleted, either on destruction of the `scoped_ptr`,
21or via an explicit `reset`. See the <<scoped_ptr_example,example>>.
22
23`scoped_ptr` is a simple solution for simple needs. It supplies a basic "resource acquisition
24is initialization" facility, without shared-ownership or transfer-of-ownership semantics.
25Both its name and enforcement of semantics (by being  noncopyable) signal its intent to retain
26ownership solely within the current scope. Because it is noncopyable, it is safer than `shared_ptr`
27for pointers which should not be copied.
28
29Because `scoped_ptr` is simple, in its usual implementation every operation is as fast as for a
30built-in pointer and it has no more space overhead that a built-in pointer.
31
32`scoped_ptr` cannot be used in {cpp} Standard Library containers. Use `shared_ptr` or `std::unique_ptr`
33if you need a smart pointer that can.
34
35`scoped_ptr` cannot correctly hold a pointer to a dynamically allocated array. See `scoped_array` for that usage.
36
37The class template is parameterized on `T`, the type of the object pointed to. Destroying `T` must not thow exceptions,
38and `T` must be complete at the point `scoped_ptr<T>::~scoped_ptr` is instantiated.
39
40## Synopsis
41
42`scoped_ptr` is defined in `<boost/smart_ptr/scoped_ptr.hpp>`.
43
44```
45namespace boost {
46
47  template<class T> class scoped_ptr {
48  private:
49
50    scoped_ptr(scoped_ptr const&);
51    scoped_ptr& operator=(scoped_ptr const&);
52
53    void operator==(scoped_ptr const&) const;
54    void operator!=(scoped_ptr const&) const;
55
56  public:
57
58    typedef T element_type;
59
60    explicit scoped_ptr(T * p = 0) noexcept;
61    ~scoped_ptr() noexcept;
62
63    void reset(T * p = 0) noexcept;
64
65    T & operator*() const noexcept;
66    T * operator->() const noexcept;
67    T * get() const noexcept;
68
69    explicit operator bool() const noexcept;
70
71    void swap(scoped_ptr & b) noexcept;
72  };
73
74  template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
75
76  template<class T>
77    bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
78  template<class T>
79    bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
80
81  template<class T>
82    bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
83  template<class T>
84    bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
85}
86```
87
88## Members
89
90### element_type
91
92    typedef T element_type;
93
94Provides the type of the stored pointer.
95
96### constructor
97
98    explicit scoped_ptr(T * p = 0) noexcept;
99
100Constructs a `scoped_ptr`, storing a copy of `p`, which must have been allocated via a
101{cpp} `new` expression or be 0. `T` is not required be a complete type.
102
103### destructor
104
105    ~scoped_ptr() noexcept;
106
107Destroys the object pointed to by the stored pointer, if any, as if by using
108`delete this\->get()`. `T` must be a complete type.
109
110### reset
111
112    void reset(T * p = 0) noexcept;
113
114Deletes the object pointed to by the stored pointer and then stores a copy of
115`p`, which must have been allocated via a {cpp} `new` expression or be 0.
116
117Since the previous object needs to be deleted, `T` must be a complete type.
118
119### indirection
120
121    T & operator*() const noexcept;
122
123Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0.
124
125    T * operator->() const noexcept;
126
127Returns the stored pointer. Behavior is undefined if the stored pointer is 0.
128
129### get
130
131    T * get() const noexcept;
132
133Returns the stored pointer. `T` need not be a complete type.
134
135### conversions
136
137    explicit operator bool () const noexcept; // never throws
138
139Returns `get() != 0`.
140
141NOTE: On C++03 compilers, the return value is of an unspecified type.
142
143### swap
144
145    void swap(scoped_ptr & b) noexcept;
146
147Exchanges the contents of the two smart pointers. `T` need not be a complete type.
148
149## Free Functions
150
151### swap
152
153    template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
154
155Equivalent to `a.swap(b)`.
156
157### comparisons
158
159    template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
160
161    template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
162
163Returns `p.get() == nullptr`.
164
165    template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
166
167    template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
168
169Returns `p.get() != nullptr`.
170
171## Example
172
173Here's an example that uses `scoped_ptr`.
174
175```
176#include <boost/scoped_ptr.hpp>
177#include <iostream>
178
179struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
180
181class MyClass {
182    boost::scoped_ptr<int> ptr;
183  public:
184    MyClass() : ptr(new int) { *ptr = 0; }
185    int add_one() { return ++*ptr; }
186};
187
188int main()
189{
190    boost::scoped_ptr<Shoe> x(new Shoe);
191    MyClass my_instance;
192    std::cout << my_instance.add_one() << '\n';
193    std::cout << my_instance.add_one() << '\n';
194}
195```
196
197The example program produces the beginning of a child's nursery rhyme:
198
199```
2001
2012
202Buckle my shoe
203```
204
205## Rationale
206
207The primary reason to use `scoped_ptr` rather than `std::auto_ptr` or `std::unique_ptr` is to let readers of your code
208know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership.
209
210A secondary reason to use `scoped_ptr` is to prevent a later maintenance programmer from adding a function that transfers
211ownership by returning the `auto_ptr`, because the maintenance programmer saw `auto_ptr`, and assumed ownership could safely be transferred.
212
213Think of `bool` vs `int`. We all know that under the covers `bool` is usually just an `int`. Indeed, some argued against including bool in the {cpp}
214standard because of that. But by coding `bool` rather than `int`, you tell your readers what your intent is. Same with `scoped_ptr`; by using it you are signaling intent.
215
216It has been suggested that `scoped_ptr<T>` is equivalent to `std::auto_ptr<T> const`. Ed Brey pointed out, however, that `reset` will not work on a `std::auto_ptr<T> const`.
217
218## Handle/Body Idiom
219
220One common usage of `scoped_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.
221
222The `link:../../example/scoped_ptr_example_test.cpp[scoped_ptr_example_test.cpp]` sample program includes a header file,
223`link:../../example/scoped_ptr_example.hpp[scoped_ptr_example.hpp]`, which uses a `scoped_ptr<>` to an incomplete type to hide the
224implementation. The instantiation of member functions which require a complete type occurs in the `link:../../example/scoped_ptr_example.cpp[scoped_ptr_example.cpp]`
225implementation file.
226
227## Frequently Asked Questions
228
229[qanda]
230Why doesn't `scoped_ptr` have a `release()` member?::
231
232  When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If `scoped_ptr` had a `release()` member,
233  it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use `std::auto_ptr` where
234  transfer of ownership is required. (supplied by Dave Abrahams)
235