From dea4e8129da97389b4fd6bb5dc8823f4e646c0a5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 12 Jun 2017 03:12:03 +0300 Subject: [PATCH] Complete scoped_ptr.adoc --- doc/smart_ptr.adoc | 5 +- doc/smart_ptr/enable_shared_from_this.adoc | 2 +- doc/smart_ptr/history.adoc | 5 +- doc/smart_ptr/introduction.adoc | 26 ++- doc/smart_ptr/intrusive_ptr.adoc | 4 +- doc/smart_ptr/intrusive_ref_counter.adoc | 2 +- doc/smart_ptr/make_shared.adoc | 4 +- doc/smart_ptr/make_unique.adoc | 4 +- doc/smart_ptr/pointer_cast.adoc | 2 +- doc/smart_ptr/pointer_to_other.adoc | 2 +- doc/smart_ptr/scoped_array.adoc | 4 +- doc/smart_ptr/scoped_ptr.adoc | 200 ++++++++++++++++++++- doc/smart_ptr/shared_array.adoc | 5 +- doc/smart_ptr/shared_ptr.adoc | 4 +- doc/smart_ptr/techniques.adoc | 5 +- doc/smart_ptr/weak_ptr.adoc | 4 +- 16 files changed, 238 insertions(+), 40 deletions(-) diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc index e85479b..361b528 100644 --- a/doc/smart_ptr.adoc +++ b/doc/smart_ptr.adoc @@ -7,10 +7,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -# Boost.SmartPtr: Smart Pointer Library +# Boost.SmartPtr: The Smart Pointer Library Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes :toc: left -:toclevels: 3 +:toclevels: 2 :idprefix: :listing-caption: Code Example :table-caption: Illustration @@ -53,6 +53,7 @@ include::smart_ptr/shared_array.adoc[] :leveloffset: -1 +[[copyright]] [appendix] ## Copyright and License diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc index 5b385cb..428fc30 100644 --- a/doc/smart_ptr/enable_shared_from_this.adoc +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # enable_shared_from_this :toc: :toc-title: -:idprefix: +:idprefix: enable_shared_from_this_ diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc index ffdb9af..9d3c9f6 100644 --- a/doc/smart_ptr/history.adoc +++ b/doc/smart_ptr/history.adoc @@ -9,9 +9,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -[appendix,#history] +[[history]] +[appendix] # History and Acknowledgments -:idprefix: +:idprefix: history_ ## Summer 1994 diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc index dec424e..ecbef1d 100644 --- a/doc/smart_ptr/introduction.adoc +++ b/doc/smart_ptr/introduction.adoc @@ -11,9 +11,7 @@ http://www.boost.org/LICENSE_1_0.txt [#introduction] # Introduction -:toc: -:toc-title: -:idprefix: +:idprefix: intro Smart pointers are objects which store pointers to dynamically allocated (heap) objects. They behave much like built-in {cpp} pointers except that they automatically delete the object @@ -28,22 +26,22 @@ acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ P This library provides five smart pointer class templates: -* `scoped_ptr`, used to contain ownership of a dynamically allocated object to the current scope; -* `scoped_array`, which provides scoped ownership for a dynamically allocated array; -* `shared_ptr`, a versatile tool for managing shared ownership of an object or array; -* `weak_ptr`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr; -* `intrusive_ptr`, a pointer to objects with an embedded reference count. +* `<>`, used to contain ownership of a dynamically allocated object to the current scope; +* `<>`, which provides scoped ownership for a dynamically allocated array; +* `<>`, a versatile tool for managing shared ownership of an object or array; +* `<>`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr; +* `<>`, a pointer to objects with an embedded reference count. `shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration. In addition, the library contains the following supporting utility functions and classes: -* `make_shared`, a factory function for creating objects that returns a `shared_ptr`; -* `make_unique`, a factory function returning `std::unique_ptr`; -* `enable_shared_from_this`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; -* `pointer_to_other`, a helper trait for converting one smart pointer type to another; -* `static_pointer_cast` and companions, generic smart pointer casts; -* `intrusive_ref_counter`, a helper base class containing a reference count. +* `<>`, a factory function for creating objects that returns a `shared_ptr`; +* `<>`, a factory function returning `std::unique_ptr`; +* `<>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; +* `<>`, a helper trait for converting one smart pointer type to another; +* `<>` and companions, generic smart pointer casts; +* `<>`, a helper base class containing a reference count. As a general rule, the destructor or `operator delete` for an object managed by pointers in the library are not allowed to throw exceptions. diff --git a/doc/smart_ptr/intrusive_ptr.adoc b/doc/smart_ptr/intrusive_ptr.adoc index 6bf4843..c22a128 100644 --- a/doc/smart_ptr/intrusive_ptr.adoc +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#intrusive_ptr] -# intrusive_ptr +# intrusive_ptr: Managing Objects with Embedded Counts :toc: :toc-title: -:idprefix: +:idprefix: intrusive_ptr_ diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc index 4a9885a..61f9ed6 100644 --- a/doc/smart_ptr/intrusive_ref_counter.adoc +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # intrusive_ref_counter :toc: :toc-title: -:idprefix: +:idprefix: intrusive_ref_counter_ diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc index 2531cfe..53af79d 100644 --- a/doc/smart_ptr/make_shared.adoc +++ b/doc/smart_ptr/make_shared.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#make_shared] -# make_shared +# make_shared: Creating shared_ptr :toc: :toc-title: -:idprefix: +:idprefix: make_shared_ diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc index 9cfec90..5caf392 100644 --- a/doc/smart_ptr/make_unique.adoc +++ b/doc/smart_ptr/make_unique.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#make_unique] -# make_unique +# make_unique: Creating unique_ptr :toc: :toc-title: -:idprefix: +:idprefix: make_unique_ diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc index 3041eeb..cd65e4e 100644 --- a/doc/smart_ptr/pointer_cast.adoc +++ b/doc/smart_ptr/pointer_cast.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # Generic Pointer Casts :toc: :toc-title: -:idprefix: +:idprefix: pointer_cast_ diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc index 4c4f74d..8522622 100644 --- a/doc/smart_ptr/pointer_to_other.adoc +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -11,5 +11,5 @@ http://www.boost.org/LICENSE_1_0.txt # pointer_to_other :toc: :toc-title: -:idprefix: +:idprefix: pointer_to_other_ diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc index 9374caa..3fbc835 100644 --- a/doc/smart_ptr/scoped_array.adoc +++ b/doc/smart_ptr/scoped_array.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#scoped_array] -# scoped_array +# scoped_array: Scoped Array Ownership :toc: :toc-title: -:idprefix: +:idprefix: scoped_array_ diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc index ba71827..d60df72 100644 --- a/doc/smart_ptr/scoped_ptr.adoc +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -8,8 +8,204 @@ http://www.boost.org/LICENSE_1_0.txt //// [#scoped_ptr] -# scoped_ptr +# scoped_ptr: Scoped Object Ownership :toc: :toc-title: -:idprefix: +:idprefix: scoped_ptr_ +## Description + +The `scoped_ptr` class template stores a pointer to a dynamically allocated object. +(Dynamically allocated objects are allocated with the {cpp} `new` expression.) The +object pointed to is guaranteed to be deleted, either on destruction of the `scoped_ptr`, +or via an explicit `reset`. See the <>. + +`scoped_ptr` is a simple solution for simple needs. It supplies a basic "resource acquisition +is initialization" facility, without shared-ownership or transfer-of-ownership semantics. +Both its name and enforcement of semantics (by being noncopyable) signal its intent to retain +ownership solely within the current scope. Because it is noncopyable, it is safer than `shared_ptr` +for pointers which should not be copied. + +Because `scoped_ptr` is simple, in its usual implementation every operation is as fast as for a +built-in pointer and it has no more space overhead that a built-in pointer. + +`scoped_ptr` cannot be used in {cpp} Standard Library containers. Use `shared_ptr` or `std::unique_ptr` +if you need a smart pointer that can. + +`scoped_ptr` cannot correctly hold a pointer to a dynamically allocated array. See `scoped_array` for that usage. + +The class template is parameterized on `T`, the type of the object pointed to. Destroying `T` must not thow exceptions, +and `T` must be complete at the point `scoped_ptr::~scoped_ptr` is instantiated. + +## Synopsis + +`scoped_ptr` is defined in ``. + +``` +namespace boost +{ + +template class scoped_ptr +{ +private: + + scoped_ptr(scoped_ptr const&); + scoped_ptr& operator=(scoped_ptr const&); + + void operator==(scoped_ptr const&) const; + void operator!=(scoped_ptr const&) const; + +public: + + typedef T element_type; + + explicit scoped_ptr(T * p = 0) noexcept; + ~scoped_ptr() noexcept; + + void reset(T * p = 0) noexcept; + + T & operator*() const noexcept; + T * operator->() const noexcept; + T * get() const noexcept; + + explicit operator bool() const noexcept; + + void swap(scoped_ptr & b) noexcept; +}; + +template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; + +} // namespace boost +``` + +## Members + +### element_type + + typedef T element_type; + +Provides the type of the stored pointer. + +### constructor + + explicit scoped_ptr(T * p = 0) noexcept; + +Constructs a `scoped_ptr`, storing a copy of `p`, which must have been allocated via a +{cpp} `new` expression or be 0. `T` is not required be a complete type. + +### destructor + + ~scoped_ptr() noexcept; + +Destroys the object pointed to by the stored pointer, if any, as if by using +`delete this\->get()`. `T` must be a complete type. + +### reset + + void reset(T * p = 0) noexcept; + +Deletes the object pointed to by the stored pointer and then stores a copy of +`p`, which must have been allocated via a {cpp} `new` expression or be 0. + +Since the previous object needs to be deleted, `T` must be a complete type. + +### indirection + + T & operator*() const noexcept; + +Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0. + + T * operator->() const noexcept; + +Returns the stored pointer. Behavior is undefined if the stored pointer is 0. + +### get + + T * get() const noexcept; + +Returns the stored pointer. `T` need not be a complete type. + +### conversions + + explicit operator bool () const noexcept; // never throws + +Returns `get() != 0`. + +### swap + + void swap(scoped_ptr & b) noexcept; + +Exchanges the contents of the two smart pointers. `T` need not be a complete type. + +## Free Functions + +### swap + + template void swap(scoped_ptr & a, scoped_ptr & b) noexcept; + +Equivalent to `a.swap(b)`. + +## Example + +Here's an example that uses `scoped_ptr`. + +``` +#include +#include + +struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } }; + +class MyClass { + boost::scoped_ptr ptr; + public: + MyClass() : ptr(new int) { *ptr = 0; } + int add_one() { return ++*ptr; } +}; + +int main() +{ + boost::scoped_ptr x(new Shoe); + MyClass my_instance; + std::cout << my_instance.add_one() << '\n'; + std::cout << my_instance.add_one() << '\n'; +} +``` + +The example program produces the beginning of a child's nursery rhyme: + +``` +1 +2 +Buckle my shoe +``` + +## Rationale + +The primary reason to use `scoped_ptr` rather than `std::auto_ptr` or `std::unique_ptr` is to let readers of your code +know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer ownership. + +A secondary reason to use `scoped_ptr` is to prevent a later maintenance programmer from adding a function that transfers +ownership by returning the `auto_ptr`, because the maintenance programmer saw `auto_ptr`, and assumed ownership could safely be transferred. + +Think 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} +standard 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. + +It has been suggested that `scoped_ptr` is equivalent to `std::auto_ptr const`. Ed Brey pointed out, however, that `reset` will not work on a `std::auto_ptr const`. + +## Handle/Body Idiom + +One 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. + +The `link:../../example/scoped_ptr_example_test.cpp[scoped_ptr_example_test.cpp]` sample program includes a header file, +`link:../../example/scoped_ptr_example.hpp[scoped_ptr_example.hpp]`, which uses a `scoped_ptr<>` to an incomplete type to hide the +implementation. The instantiation of member functions which require a complete type occurs in the `link:../../example/scoped_ptr_example.cpp[scoped_ptr_example.cpp]` +implementation file. + +## Frequently Asked Questions + +[qanda] +Why doesn't `scoped_ptr` have a `release()` member?:: + + 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, + 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 + transfer of ownership is required. (supplied by Dave Abrahams) diff --git a/doc/smart_ptr/shared_array.adoc b/doc/smart_ptr/shared_array.adoc index 564747f..aa2933f 100644 --- a/doc/smart_ptr/shared_array.adoc +++ b/doc/smart_ptr/shared_array.adoc @@ -7,9 +7,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -[appendix,#shared_array] +[[shared_array]] +[appendix] # shared_array (deprecated) :toc: :toc-title: -:idprefix: +:idprefix: shared_array_ diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index 50e38a0..5a34eeb 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#shared_ptr] -# shared_ptr +# shared_ptr: Shared Ownership :toc: :toc-title: -:idprefix: +:idprefix: shared_ptr_ diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc index 13a9b18..5f26036 100644 --- a/doc/smart_ptr/techniques.adoc +++ b/doc/smart_ptr/techniques.adoc @@ -7,9 +7,10 @@ See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt //// -[appendix,#techniques] +[[techniques]] +[appendix] # Smart Pointer Programming Techniques :toc: :toc-title: -:idprefix: +:idprefix: techniques_ diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc index ceb28cf..c5a740c 100644 --- a/doc/smart_ptr/weak_ptr.adoc +++ b/doc/smart_ptr/weak_ptr.adoc @@ -8,8 +8,8 @@ http://www.boost.org/LICENSE_1_0.txt //// [#weak_ptr] -# weak_ptr +# weak_ptr: Non-owning Observer :toc: :toc-title: -:idprefix: +:idprefix: weak_ptr_