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