diff --git a/compatibility.htm b/compatibility.htm deleted file mode 100644 index 6f57e4d..0000000 --- a/compatibility.htm +++ /dev/null @@ -1,88 +0,0 @@ - - - - Smart Pointer Changes - - - -

boost.png (6897 bytes)Smart Pointer Changes

-

The February 2002 change to the Boost smart pointers introduced a number of - changes. Since the previous version of the smart pointers was in use for a long - time, it's useful to have a detailed list of what changed from a library user's - point of view.

-

Note that for compilers that don't support member templates well enough, a - separate implementation is used that lacks many of the new features and is more - like the old version.

-

Features Requiring Code Changes to Take Advantage

- -

Features That Improve Robustness

- -

Implementation Details

- -
-

$Date$

-

Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000..0972e2d --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +/html/ +/pdf/ diff --git a/doc/Jamfile b/doc/Jamfile new file mode 100644 index 0000000..b6d2c35 --- /dev/null +++ b/doc/Jamfile @@ -0,0 +1,26 @@ +# Copyright 2017 Peter Dimov +# +# Distributed under the Boost Software License, Version 1.0. +# +# See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt + +project doc/smart_ptr ; + +import asciidoctor ; + +html smart_ptr.html : smart_ptr.adoc ; + +install html_ : smart_ptr.html : html ; + +pdf smart_ptr.pdf : smart_ptr.adoc ; +explicit smart_ptr.pdf ; + +install pdf_ : smart_ptr.pdf : pdf ; +explicit pdf_ ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : html_ ; +explicit boostrelease ; diff --git a/doc/asciidoctor.jam b/doc/asciidoctor.jam new file mode 100644 index 0000000..488670d --- /dev/null +++ b/doc/asciidoctor.jam @@ -0,0 +1,50 @@ +# Copyright 2017 Peter Dimov +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +import type ; +import scanner ; +import generators ; +import boostbook ; + +# File type + +type.register ASCIIDOC : asciidoc adoc ; + +# Define dependency scanner + +class asciidoc-scanner : common-scanner +{ + rule pattern ( ) + { + return "include::([^[]+)\\[" ; + } +} + +scanner.register asciidoc-scanner : include ; +type.set-scanner ASCIIDOC : asciidoc-scanner ; + +# Define generators + +generators.register-standard asciidoctor.asciidoc-to-html : ASCIIDOC : HTML ; +generators.register-standard asciidoctor.asciidoc-to-pdf : ASCIIDOC : PDF ; +# generators.register-standard asciidoctor.asciidoc-to-docbook : ASCIIDOC : DOCBOOK ; + +# Define actions + +actions asciidoc-to-html +{ + asciidoctor -b html -o $(1) $(2) +} + +actions asciidoc-to-pdf +{ + asciidoctor -r asciidoctor-pdf -b pdf -o $(1) $(2) +} + +actions asciidoc-to-docbook +{ + asciidoctor -b docbook -o $(1) $(2) +} diff --git a/doc/smart_ptr-docinfo-footer.html b/doc/smart_ptr-docinfo-footer.html new file mode 100644 index 0000000..8cf495c --- /dev/null +++ b/doc/smart_ptr-docinfo-footer.html @@ -0,0 +1,33 @@ + + + diff --git a/doc/smart_ptr.adoc b/doc/smart_ptr.adoc new file mode 100644 index 0000000..5b452c7 --- /dev/null +++ b/doc/smart_ptr.adoc @@ -0,0 +1,70 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +# Boost.SmartPtr: The Smart Pointer Library +Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes +:toc: left +:toclevels: 2 +:idprefix: +:listing-caption: Code Example +:docinfo: private-footer + +:leveloffset: +1 + +include::smart_ptr/introduction.adoc[] + +include::smart_ptr/scoped_ptr.adoc[] + +include::smart_ptr/scoped_array.adoc[] + +include::smart_ptr/shared_ptr.adoc[] + +include::smart_ptr/weak_ptr.adoc[] + +include::smart_ptr/make_shared.adoc[] + +include::smart_ptr/enable_shared_from_this.adoc[] + +include::smart_ptr/make_unique.adoc[] + +include::smart_ptr/intrusive_ptr.adoc[] + +include::smart_ptr/intrusive_ref_counter.adoc[] + +include::smart_ptr/pointer_cast.adoc[] + +include::smart_ptr/pointer_to_other.adoc[] + +// appendix +include::smart_ptr/techniques.adoc[] + +// appendix +include::smart_ptr/history.adoc[] + +// appendix, deprecated +include::smart_ptr/shared_array.adoc[] + +:leveloffset: -1 + +[[copyright]] +[appendix] +## Copyright and License + +This documentation is + +* Copyright 1999 Greg Colvin +* Copyright 1999 Beman Dawes +* Copyright 2002 Darin Adler +* Copyright 2003-2017 Peter Dimov +* Copyright 2005, 2006 Ion Gaztañaga +* Copyright 2008 Frank Mori Hess +* Copyright 2012-2017 Glen Fernandes +* Copyright 2013 Andrey Semashev + +and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0]. diff --git a/doc/smart_ptr/enable_shared_from_this.adoc b/doc/smart_ptr/enable_shared_from_this.adoc new file mode 100644 index 0000000..757c1d4 --- /dev/null +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -0,0 +1,144 @@ +//// +Copyright 2002, 2003, 2015, 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#enable_shared_from_this] +# enable_shared_from_this +:toc: +:toc-title: +:idprefix: enable_shared_from_this_ + +## Description + +The class template `enable_shared_from_this` is used as a base class that allows +a `shared_ptr` or a `weak_ptr` to the current object to be obtained from within a +member function. + +`enable_shared_from_this` defines two member functions called `shared_from_this` +that return a `shared_ptr` and `shared_ptr`, depending on constness, to +`this`. It also defines two member functions called `weak_from_this` that return a +corresponding `weak_ptr`. + +## Example + +``` +#include +#include +#include + +class Y: public boost::enable_shared_from_this +{ +public: + + boost::shared_ptr f() + { + return shared_from_this(); + } +}; + +int main() +{ + boost::shared_ptr p(new Y); + boost::shared_ptr q = p->f(); + assert(p == q); + assert(!(p < q || q < p)); // p and q must share ownership +} +``` + +## Synopsis + +`enable_shared_from_this` is defined in ``. + +``` +namespace boost { + + template class enable_shared_from_this { + private: + + // exposition only + weak_ptr weak_this_; + + protected: + + enable_shared_from_this() = default; + ~enable_shared_from_this() = default; + + enable_shared_from_this(const enable_shared_from_this&) noexcept; + enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept; + + public: + + shared_ptr shared_from_this(); + shared_ptr shared_from_this() const; + + weak_ptr weak_from_this() noexcept; + weak_ptr weak_from_this() const noexcept; + } +} +``` + +## Members + +``` +enable_shared_from_this(enable_shared_from_this const &) noexcept; +``` +[none] +* {blank} ++ +Effects:: Default-constructs `weak_this_`. + +NOTE: `weak_this_` is _not_ copied from the argument. + +``` +enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept; +``` +[none] +* {blank} ++ +Returns:: `*this`. + +NOTE: `weak_this_` is unchanged. + +``` +template shared_ptr shared_from_this(); +``` +``` +template shared_ptr shared_from_this() const; +``` +[none] +* {blank} ++ +Returns:: `shared_ptr(weak_this_)`. + +NOTE: These members throw `bad_weak_ptr` when `*this` is not owned by a `shared_ptr`. + +[NOTE] +==== +`weak_this_` is initialized by `shared_ptr` to a copy of itself when it's constructed by a pointer to `*this`. +For example, in the following code: +``` +class Y: public boost::enable_shared_from_this {}; + +int main() +{ + boost::shared_ptr p(new Y); +} +``` +the construction of `p` will automatically initialize `p\->weak_this_` to `p`. +==== + +``` +template weak_ptr weak_from_this() noexcept; +``` +``` +template weak_ptr weak_from_this() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `weak_this_`. diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc new file mode 100644 index 0000000..9e60a7a --- /dev/null +++ b/doc/smart_ptr/history.adoc @@ -0,0 +1,108 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[[history]] +[appendix] +# History and Acknowledgments +:idprefix: history_ + +## Summer 1994 + +Greg Colvin http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf[proposed] +to the {cpp} Standards Committee classes named `auto_ptr` and `counted_ptr` which were very +similar to what we now call `scoped_ptr` and `shared_ptr`. In one of the very few cases +where the Library Working Group's recommendations were not followed by the full committee, +`counted_ptr` was rejected and surprising transfer-of-ownership semantics were added to `auto_ptr`. + +## October 1998 + +Beman Dawes proposed reviving the original semantics under the names `safe_ptr` and `counted_ptr`, +meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, +Dietmar Kühl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new class +names were finalized, it was decided that there was no need to exactly follow the `std::auto_ptr` +interface, and various function signatures and semantics were finalized. + +Over the next three months, several implementations were considered for `shared_ptr`, and discussed +on the http://www.boost.org/[boost.org] mailing list. The implementation questions revolved around +the reference count which must be kept, either attached to the pointed to object, or detached elsewhere. +Each of those variants have themselves two major variants: + +* Direct detached: the `shared_ptr` contains a pointer to the object, and a pointer to the count. +* Indirect detached: the `shared_ptr` contains a pointer to a helper object, which in turn contains a pointer to the object and the count. +* Embedded attached: the count is a member of the object pointed to. +* Placement attached: the count is attached via operator new manipulations. + +Each implementation technique has advantages and disadvantages. We went so far as to run various timings +of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little +measurable difference. Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar Kühl +suggested an elegant partial template specialization technique to allow users to choose which implementation +they preferred, and that was also experimented with. + +But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose +to supply only the direct implementation. + +## May 1999 + +In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements. + +## September 1999 + +Luis Coelho provided `shared_ptr::swap` and `shared_array::swap`. + +## November 1999 + +Darin Adler provided `operator ==`, `operator !=`, and `std::swap` and `std::less` specializations for shared types. + +## May 2001 + +Vladimir Prus suggested requiring a complete type on destruction. Refinement evolved in discussions including Dave Abrahams, +Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others. + +## January 2002 + +Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding +`weak_ptr`. + +## March 2003 + +Peter Dimov, Beman Dawes and Greg Colvin http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html[proposed] `shared_ptr` +and `weak_ptr` for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was +accepted and eventually went on to become a part of the {cpp} standard in its 2011 iteration. + +## July 2007 + +Peter Dimov and Beman Dawes http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm[proposed] a number of enhancements +to `shared_ptr` as it was entering the working paper that eventually became the {cpp}11 standard. + +## November 2012 + +Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation +for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization +and no value initialization. + +Peter Dimov aided this development by extending `shared_ptr` to support arrays via the syntax `shared_ptr` and `shared_ptr`. + +## April 2013 + +Peter Dimov http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.html[proposed] the extension of `shared_ptr` to support +arrays for inclusion into the standard, and it was accepted. + +## February 2014 + +Glen Fernandes updated `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper +http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], and implemented `make_unique` for arrays and objects. + +Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve {cpp} standard library defect 2070. + +## February 2017 + +Glen Fernandes rewrote `allocate_shared` and `make_shared` for arrays for a more optimal and more maintainable implementation. + diff --git a/doc/smart_ptr/introduction.adoc b/doc/smart_ptr/introduction.adoc new file mode 100644 index 0000000..ecbef1d --- /dev/null +++ b/doc/smart_ptr/introduction.adoc @@ -0,0 +1,47 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#introduction] +# Introduction +: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 +pointed to at the appropriate time. Smart pointers are particularly useful in the face of +exceptions as they ensure proper destruction of dynamically allocated objects. They can also be +used to keep track of dynamically allocated objects shared by multiple owners. + +Conceptually, smart pointers are seen as owning the object pointed to, and thus responsible for +deletion of the object when it is no longer needed. As such, they are examples of the "resource +acquisition is initialization" idiom described in Bjarne Stroustrup's "The C++ Programming Language", +3rd edition, Section 14.4, Resource Management. + +This library provides five smart pointer class templates: + +* `<>`, 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: + +* `<>`, 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 new file mode 100644 index 0000000..1c729cd --- /dev/null +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -0,0 +1,447 @@ +//// +Copyright 2003-2005, 2013, 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#intrusive_ptr] +# intrusive_ptr: Managing Objects with Embedded Counts +:toc: +:toc-title: +:idprefix: intrusive_ptr_ + +## Description + +The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count. +Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the +function `intrusive_ptr_add_ref`, passing it the pointer as an argument. Similarly, when an `intrusive_ptr` +is destroyed, it calls `intrusive_ptr_release`; this function is responsible for destroying the object when +its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. +On compilers that support argument-dependent lookup, `intrusive_ptr_add_ref` and `intrusive_ptr_release` should +be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace +`boost`. The library provides a helper base class template `<>` which +may help adding support for `intrusive_ptr` to user types. + +The class template is parameterized on `T`, the type of the object pointed to. `intrusive_ptr` can be implicitly +converted to `intrusive_ptr` whenever `T*` can be implicitly converted to `U*`. + +The main reasons to use `intrusive_ptr` are: + +* Some existing frameworks or OSes provide objects with embedded reference counts; +* The memory footprint of `intrusive_ptr` is the same as the corresponding raw pointer; +* `intrusive_ptr` can be constructed from an arbitrary raw pointer of type `T*`. + +As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your needs than `shared_ptr`, try a `shared_ptr`-based design first. + +## Synopsis + +`intrusive_ptr` is defined in ``. + +``` +namespace boost { + + template class intrusive_ptr { + public: + + typedef T element_type; + + intrusive_ptr() noexcept; + intrusive_ptr(T * p, bool add_ref = true); + + intrusive_ptr(intrusive_ptr const & r); + template intrusive_ptr(intrusive_ptr const & r); + + ~intrusive_ptr(); + + intrusive_ptr & operator=(intrusive_ptr const & r); + template intrusive_ptr & operator=(intrusive_ptr const & r); + intrusive_ptr & operator=(T * r); + + void reset(); + void reset(T * r); + void reset(T * r, bool add_ref); + + T & operator*() const noexcept; + T * operator->() const noexcept; + T * get() const noexcept; + T * detach() noexcept; + + explicit operator bool () const noexcept; + + void swap(intrusive_ptr & b) noexept; + }; + + template + bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + + template + bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + + template + bool operator==(intrusive_ptr const & a, U * b) noexcept; + + template + bool operator!=(intrusive_ptr const & a, U * b) noexcept; + + template + bool operator==(T * a, intrusive_ptr const & b) noexcept; + + template + bool operator!=(T * a, intrusive_ptr const & b) noexcept; + + template + bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; + + template void swap(intrusive_ptr & a, intrusive_ptr & b) noexcept; + + template T * get_pointer(intrusive_ptr const & p) noexcept; + + template + intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; + + template + intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; + + template + intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; + + template + std::basic_ostream & operator<< (std::basic_ostream & os, + intrusive_ptr const & p); +} +``` + +## Members + +### element_type + +``` +typedef T element_type; +``` + +Provides the type of the template parameter T. + +### constructors + +``` +intrusive_ptr() noexcept; +``` + +[none] +* {blank} ++ +Postconditions:: `get() == 0`. + +``` +intrusive_ptr(T * p, bool add_ref = true); +``` + +[none] +* {blank} ++ +Effects:: `if(p != 0 && add_ref) intrusive_ptr_add_ref(p);`. +Postconditions:: `get() == p`. + +``` +intrusive_ptr(intrusive_ptr const & r); +``` +``` +template intrusive_ptr(intrusive_ptr const & r); +``` + +[none] +* {blank} ++ +Effects:: `if(r.get() != 0) intrusive_ptr_add_ref(r.get());`. +Postconditions:: `get() == r.get()`. + +### destructor + +``` +~intrusive_ptr(); +``` + +[none] +* {blank} ++ +Effects:: `if(get() != 0) intrusive_ptr_release(get());`. + +### assignment + +``` +intrusive_ptr & operator=(intrusive_ptr const & r); +``` +``` +template intrusive_ptr & operator=(intrusive_ptr const & r); +``` +``` +intrusive_ptr & operator=(T * r); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. +Returns:: `*this`. + +### reset + +``` +void reset(); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr().swap(*this)`. + +``` +void reset(T * r); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. + +``` +void reset(T * r, bool add_ref); +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `intrusive_ptr(r, add_ref).swap(*this)`. + +### indirection + +``` +T & operator*() const noexcept; +``` + +[none] +* {blank} ++ +Requirements:: `get() != 0`. +Returns:: `*get()`. + +``` +T * operator->() const noexcept; +``` + +[none] +* {blank} ++ +Requirements:: `get() != 0`. +Returns:: `get()`. + +### get + +``` +T * get() const noexcept; +``` + +[none] +* {blank} ++ +Returns:: the stored pointer. + +### detach + +``` +T * detach() noexcept; +``` + +[none] +* {blank} ++ +Returns:: the stored pointer. +Postconditions:: `get() == 0`. + +NOTE: The returned pointer has an elevated reference count. This allows conversion of an `intrusive_ptr` +back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference. +It can be viewed as the complement of the non-reference-incrementing constructor. + +CAUTION: Using `detach` escapes the safety of automatic reference counting provided by `intrusive_ptr`. +It should by used only where strictly necessary (such as when interfacing to an existing API), and when +the implications are thoroughly understood. + +### conversions + +``` +explicit operator bool () const noexcept; +``` + +[none] +* {blank} ++ +Returns:: `get() != 0`. + +NOTE: This conversion operator allows `intrusive_ptr` objects to be used in boolean contexts, +like `if (p && p\->valid()) {}`. + +NOTE: On C++03 compilers, the return value is of an unspecified type. + +### swap + +``` +void swap(intrusive_ptr & b) noexcept; +``` + +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +## Free Functions + +### comparison + +``` +template + bool operator==(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() == b.get()`. + +``` +template + bool operator!=(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() != b.get()`. + +``` +template + bool operator==(intrusive_ptr const & a, U * b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() == b`. + +``` +template + bool operator!=(intrusive_ptr const & a, U * b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a.get() != b`. + +``` +template + bool operator==(T * a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a == b.get()`. + +``` +template + bool operator!=(T * a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `a != b.get()`. + +``` +template + bool operator<(intrusive_ptr const & a, intrusive_ptr const & b) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `std::less()(a.get(), b.get())`. + +NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers. + +### swap + +``` +template void swap(intrusive_ptr & a, intrusive_ptr & b) noexcept; +``` + +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +### get_pointer + +``` +template T * get_pointer(intrusive_ptr const & p) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `p.get()`. + +NOTE: Provided as an aid to generic programming. Used by `mem_fn`. + +### static_pointer_cast + +``` +template + intrusive_ptr static_pointer_cast(intrusive_ptr const & r) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `intrusive_ptr(static_cast(r.get()))`. + +### const_pointer_cast + +``` +template + intrusive_ptr const_pointer_cast(intrusive_ptr const & r) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `intrusive_ptr(const_cast(r.get()))`. + +### dynamic_pointer_cast + +``` +template + intrusive_ptr dynamic_pointer_cast(intrusive_ptr const & r) noexcept; +``` + +[none] +* {blank} ++ +Returns:: `intrusive_ptr(dynamic_cast(r.get()))`. + +### operator<< + +``` +template + std::basic_ostream & operator<< (std::basic_ostream & os, + intrusive_ptr const & p); +``` + +[none] +* {blank} ++ +Effects:: `os << p.get();`. +Returns:: `os`. diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc new file mode 100644 index 0000000..1d33300 --- /dev/null +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -0,0 +1,142 @@ +//// +Copyright 2017 Peter Dimov +Copyright 2013 Andrey Semashev + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#intrusive_ref_counter] +# intrusive_ref_counter +:toc: +:toc-title: +:idprefix: intrusive_ref_counter_ + +## Description + +The `intrusive_ref_counter` class template implements a reference counter for +a derived user's class that is intended to be used with `intrusive_ptr`. The +base class has associated `intrusive_ptr_add_ref` and `intrusive_ptr_release` +functions which modify the reference counter as needed and destroy the user's +object when the counter drops to zero. + +The class template is parameterized on `Derived` and `CounterPolicy` +parameters. The first parameter is the user's class that derives from +`intrusive_ref_counter`. This type is needed in order to destroy the object +correctly when there are no references to it left. + +The second parameter is a policy that defines the nature of the reference +counter. The library provides two such policies: `thread_unsafe_counter` and +`thread_safe_counter`. The former instructs the `intrusive_ref_counter` base +class to use a counter only suitable for a single-threaded use. Pointers to a +single object that uses this kind of reference counter must not be used in +different threads. The latter policy makes the reference counter thread-safe, +unless the target platform doesn't support threading. Since in modern systems +support for threading is common, the default counter policy is +`thread_safe_counter`. + +## Synopsis + +`intrusive_ref_counter` is defined in +``. + +``` +namespace boost { + struct thread_unsafe_counter; + struct thread_safe_counter; + + template + class intrusive_ref_counter { + public: + intrusive_ref_counter() noexcept; + intrusive_ref_counter(const intrusive_ref_counter& v) noexcept; + + intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; + + unsigned int use_count() const noexcept; + + protected: + ~intrusive_ref_counter() = default; + }; + + template + void intrusive_ptr_add_ref( + const intrusive_ref_counter* p) noexcept; + + template + void intrusive_ptr_release( + const intrusive_ref_counter* p) noexcept; +} +``` + +## Members + +### Constructors + +``` +intrusive_ref_counter() noexcept; +``` +:: +``` +intrusive_ref_counter(const intrusive_ref_counter&) noexcept; +``` +:: +Postconditions::: `use_count() == 0`. + +NOTE: The pointer to the constructed object is expected to be passed to +`intrusive_ptr` constructor, assignment operator or `reset` method, which +would increment the reference counter. + +### Destructor + +``` +~intrusive_ref_counter(); +``` +:: +Effects::: Destroys the counter object. + +NOTE: The destructor is protected so that the object can only be destroyed +through the `Derived` class. + +### Assignment + +``` +intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; +``` +:: +Effects::: Does nothing, reference counter is not modified. +y +### use_count + +``` +unsigned int use_count() const noexcept; +``` +:: +Returns::: The current value of the reference counter. + +NOTE: The returned value may not be actual in multi-threaded applications. + +## Free Functions + +### intrusive_ptr_add_ref + +``` +template + void intrusive_ptr_add_ref( + const intrusive_ref_counter* p) noexcept; +``` +:: +Effects::: Increments the reference counter. + +### intrusive_ptr_release + +``` +template + void intrusive_ptr_release( + const intrusive_ref_counter* p) noexcept; +``` +:: +Effects::: Decrements the reference counter. If the reference counter reaches +0, calls `delete static_cast(p)`. diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc new file mode 100644 index 0000000..5b4366c --- /dev/null +++ b/doc/smart_ptr/make_shared.adoc @@ -0,0 +1,295 @@ +//// +Copyright 2017 Peter Dimov +Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#make_shared] +# make_shared: Creating shared_ptr +:toc: +:toc-title: +:idprefix: make_shared_ + +## Description + +The function templates `make_shared` and `allocate_shared` provide convenient, +safe and efficient ways to create `shared_ptr` objects. + +## Rationale + +Consistent use of `shared_ptr` can eliminate the need to use an explicit +`delete`, but alone it provides no support in avoiding explicit `new`. There +were repeated requests from users for a factory function that creates an +object of a given type and returns a `shared_ptr` to it. Besides convenience +and style, such a function is also exception safe and considerably faster +because it can use a single allocation for both the object and its +corresponding control block, eliminating a significant portion of +`shared_ptr` construction overhead. This eliminates one of the major +efficiency complaints about `shared_ptr`. + +The family of overloaded function templates, `make_shared` and +`allocate_shared`, were provided to address this need. `make_shared` uses the +global `operator new` to allocate memory, whereas `allocate_shared` uses an +user-supplied allocator, allowing finer control. + +The rationale for choosing the name `make_shared` is that the expression +`make_shared()` can be read aloud and conveys the intended meaning. + +Originally the Boost function templates `allocate_shared` and `make_shared` +were provided for scalar objects only. There was a need to have efficient +allocation of array objects. One criticism of class template `shared_array` +was always the lack of a utility like `make_shared` that uses only a single +allocation. When `shared_ptr` was enhanced to support array types, additional +overloads of `allocate_shared` and `make_shared` were provided for array +types. + +## Synopsis + +`make_shared` and `allocate_shared` are defined in +``. + +[subs=+quotes] +``` +namespace boost { + `// only if T is not an array type` + template + shared_ptr make_shared(Args&&... args); + template + shared_ptr allocate_shared(const A& a, Args&&... args); + + `// only if T is an array type of the form U[]` + template + shared_ptr make_shared(std::size_t n); + template + shared_ptr allocate_shared(const A& a, std::size_t n); + + `// only if T is an array type of the form U[N]` + template + shared_ptr make_shared(); + template + shared_ptr allocate_shared(const A& a); + + `// only if T is an array type of the form U[]` + template shared_ptr + make_shared(std::size_t n, const remove_extent_t& v); + template shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); + + `// only if T is an array type of the form U[N]` + template + shared_ptr make_shared(const remove_extent_t& v); + template + shared_ptr allocate_shared(const A& a, const remove_extent_t& v); + + `// only if T is not an array type of the form U[]` + template + shared_ptr make_shared_noinit(); + template + shared_ptr allocate_shared_noinit(const A& a); + + `// only if T is an array type of the form U[N]` + template + shared_ptr make_shared_noinit(std::size_t n); + template + shared_ptr allocate_shared_noinit(const A& a, std::size_t n); +} +``` + +## Common Requirements + +The common requirements that apply to all `make_shared` and `allocate_shared` +overloads, unless specified otherwise, are described below. + +Requires:: `A` shall be an _allocator_. The copy constructor and destructor +of `A` shall not throw exceptions. + +Effects:: Allocates memory for an object of type `T` or `n` objects of `U` +(if `T` is an array type of the form `U[]` and `n` is determined by +arguments, as specified by the concrete overload). The object is initialized +from arguments as specified by the concrete overload. Uses a rebound copy of +`a` (for an unspecified `value_type`) to allocate memory. If an exception is +thrown, the functions have no effect. + +Returns:: A `shared_ptr` instance that stores and owns the address of the +newly constructed object. + +Postconditions:: `r.get() != 0` and `r.use_count() == 1`, where `r` +is the return value. + +Throws:: `std::bad_alloc`, an exception thrown from `A::allocate`, or from the +initialization of the object. + +Remarks:: +* Performs no more than one memory allocation. This provides efficiency +equivalent to an intrusive smart pointer. +* When an object of an array type is specified to be initialized to a value of +the same type `v`, this shall be interpreted to mean that each array element +of the object is initialized to the corresponding element from `v`. +* When an object of an array type is specified to be value-initialized, this +shall be interpreted to mean that each array element of the object is +value-initialized. +* When a (sub)object of non-array type `U` is specified to be initialized to +a value `v`, or constructed from `args\...`, `make_shared` shall perform +this initialization via the expression `::new(p) U(expr)` (where +`_expr_` is `v` or `std::forward(args)\...)` respectively) and `p` +has type `void*` and points to storage suitable to hold an object of type +`U`. +* When a (sub)object of non-array type `U` is specified to be initialized to +a value `v`, or constructed from `args\...`, `allocate_shared` shall +perform this initialization via the expression +`std::allocator_traits::construct(a2, p, expr)` (where +`_expr_` is `v` or `std::forward(args)\...)` respectively), `p` +points to storage suitable to hold an object of type `U`, and `a2` of +type `A2` is a rebound copy `a` such that its `value_type` is `U`. +* When a (sub)object of non-array type `U` is specified to be +default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall +perform this initialization via the expression `::new(p) U`, where +`p` has type `void*` and points to storage suitable to hold an object of +type `U`. +* When a (sub)object of non-array type `U` is specified to be +value-initialized, `make_shared` shall perform this initialization via the +expression `::new(p) U()`, where `p` has type `void*` and points to +storage suitable to hold an object of type `U`. +* When a (sub)object of non-array type `U` is specified to be +value-initialized, `allocate_shared` shall perform this initialization via the +expression `std::allocator_traits::construct(a2, p)`, where +`p` points to storage suitable to hold an object of type `U` and `a2` of +type `A2` is a rebound copy of `a` such that its value_type is `U`. +* Array elements are initialized in ascending order of their addresses. +* When the lifetime of the object managed by the return value ends, or when +the initialization of an array element throws an exception, the initialized +elements should be destroyed in the reverse order of their construction. + +NOTE: These functions will typically allocate more memory than the total size +of the element objects to allow for internal bookkeeping structures such as +the reference counts. + +## Free Functions + +``` +template + shared_ptr make_shared(Args&&... args); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a, Args&&... args); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: A `shared_ptr` to an object of type `T`, constructed from +`args\...`. +Examples::: +* `auto p = make_shared();` +* `auto p = make_shared >(16, 1);` + +``` +template + shared_ptr make_shared(std::size_t n); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a, std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[]`. +Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of +type `U`. +Examples::: +* `auto p = make_shared(1024);` +* `auto p = make_shared(6);` + +``` +template + shared_ptr make_shared(); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[N]`. +Returns::: A `shared_ptr` to a sequence of `N` value-initialized objects of +type `U`. +Examples::: +* `auto p = make_shared();` +* `auto p = make_shared();` + +``` +template shared_ptr + make_shared(std::size_t n, const remove_extent_t& v); +``` +:: +``` +template shared_ptr + allocate_shared(const A& a, std::size_t n, const remove_extent_t& v); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[]`. +Returns::: A `shared_ptr` to a sequence of `n` objects of type `U`, each +initialized to `v`. +Examples::: +* `auto p = make_shared(1024, 1.0);` +* `auto p = make_shared(6, {1.0, 0.0});` +* `auto p = make_shared[]>(4, {1, 2});` + +``` +template + shared_ptr make_shared(const remove_extent_t& v); +``` +:: +``` +template + shared_ptr allocate_shared(const A& a, const remove_extent_t& v); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[N]`. +Returns::: A `shared_ptr` to a sequence of `N` objects of type `U`, each +initialized to `v`. +Examples::: +* `auto p = make_shared(1.0);` +* `auto p = make_shared({1.0, 0.0});` +* `auto p = make_shared[4]>({1, 2});` + +``` +template + shared_ptr make_shared_noinit(); +``` +:: +``` +template + shared_ptr allocate_shared_noinit(const A& a); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type, or an array type of the `U[N]`. +Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a +sequence of `N` default-initialized objects of type `U`, respectively. +Example::: `auto p = make_shared_noinit();` + +``` +template + shared_ptr make_shared_noinit(std::size_t n); +``` +:: +``` +template + shared_ptr allocate_shared_noinit(const A& a, std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[]`. +Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects +of type `U`. +Example::: `auto p = make_shared_noinit(1024);` diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc new file mode 100644 index 0000000..b4e94bf --- /dev/null +++ b/doc/smart_ptr/make_unique.adoc @@ -0,0 +1,115 @@ +//// +Copyright 2017 Peter Dimov +Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#make_unique] +# make_unique: Creating unique_ptr +:toc: +:toc-title: +:idprefix: make_unique_ + +## Description + +The `make_unique` function templates provide convenient and safe ways to +create `std::unique_ptr` objects. + +## Rationale + +The {cpp}11 standard introduced `std::unique_ptr` but did not provide any +`make_unique` utility like `std::make_shared` that provided the same +exception safety and facility to avoid writing `new` expressions. Before it +was implemented by some standard library vendors (and prior to the {cpp}14 +standard introducing `std::make_unique`), this library provided it due to +requests from users. + +This library also provides additional overloads of `make_unique` for +default-initialization, when users do not need or want to incur the expense +of value-initialization. The {cpp} standard does not yet provide this +feature with `std::make_unique`. + +## Synopsis + +`make_unique` is defined in ``. + +[subs=+quotes] +``` +namespace boost { + `// only if T is not an array type` + template + std::unique_ptr make_unique(Args&&... args); + + `// only if T is not an array type` + template + std::unique_ptr make_unique(remove_reference_t&& v); + + `// only if T is an array type of the form U[]` + template + std::unique_ptr make_unique(std::size_t n); + + `// only if T is not an array type` + template + std::unique_ptr make_unique_noinit(); + + `// only if T is an array type of the form U[]` + template + std::unique_ptr make_unique_noinit(std::size_t n); +} +``` + +## Free Functions + +``` +template + std::unique_ptr make_unique(Args&&... args); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: `std::unique_ptr(new T(std::forward(args)\...)`. +Example::: `auto p = make_unique();` + +``` +template + std::unique_ptr make_unique(remove_reference_t&& v); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: `std::unique_ptr(new T(std::move(v))`. +Example::: `auto p = make_unique >({1, 2});` + +``` +template + std::unique_ptr make_unique(std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[]`. +Returns::: `std::unique_ptr(new U[n]())`. +Example::: `auto p = make_unique(1024);` + +``` +template + std::unique_ptr make_unique_noinit(); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is not an array type. +Returns::: `std::unique_ptr(new T)`. +Example::: `auto p = make_unique_noinit();` + +``` +template + std::unique_ptr make_unique_noinit(std::size_t n); +``` +:: +Remarks::: These overloads shall only participate in overload resolution when +`T` is an array type of the form `U[]`. +Returns::: `std::unique_ptr(new U[n])`. +Example::: `auto p = make_unique_noinit(1024);` diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc new file mode 100644 index 0000000..ccae283 --- /dev/null +++ b/doc/smart_ptr/pointer_cast.adoc @@ -0,0 +1,213 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#pointer_cast] +# Generic Pointer Casts +:toc: +:toc-title: +:idprefix: pointer_cast_ + +## Description + +The pointer cast function templates (`static_pointer_cast`, +`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`) +provide a way to write generic pointer castings for raw pointers, +`std::shared_ptr` and `std::unique_ptr`. + +There is test and example code in +link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp] + +## Rationale + +Boost smart pointers usually overload those functions to provide a mechanism +to emulate pointers casts. For example, `shared_ptr` implements a static +pointer cast this way: + +``` +template + shared_ptr static_pointer_cast(const shared_ptr& p); +``` + +Pointer cast functions templates are overloads of `static_pointer_cast`, +`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast` +for raw pointers, `std::shared_ptr` and `std::unique_ptr`. This way when +developing pointer type independent classes, for example, memory managers or +shared memory compatible classes, the same code can be used for raw and smart +pointers. + +## Synopsis + +The generic pointer casts are defined in ``. + +``` +namespace boost { + template T* static_pointer_cast(U* p) noexcept; + template T* dynamic_pointer_cast(U* p) noexcept; + template T* const_pointer_cast(U* p) noexcept; + template T* reinterpret_pointer_cast(U* p) noexcept; + + template std::shared_ptr + static_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + dynamic_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + const_pointer_cast(const std::shared_ptr& p) noexcept; + template std::shared_ptr + reinterpret_pointer_cast(const std::shared_ptr& p) noexcept; + + template std::unique_ptr + static_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + dynamic_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + const_pointer_cast(std::unique_ptr&& p) noexcept; + template std::unique_ptr + reinterpret_pointer_cast(std::unique_ptr&& p) noexcept; +} +``` + +## Free Functions + +### static_pointer_cast +``` +template T* static_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `static_cast(p)` + +``` +template std::shared_ptr + static_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::static_pointer_cast(p)` + +``` +template std::unique_ptr + static_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `static_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(static_cast::element_type*>(p.release()))`. + +CAUTION: The seemingly equivalent expression +`std::unique_ptr(static_cast(p.get()))` will eventually result in +undefined behavior, attempting to delete the same object twice. + +### dynamic_pointer_cast + +``` +template T* dynamic_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `dynamic_cast(p)` + +``` +template std::shared_ptr + dynamic_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::dynamic_pointer_cast(p)` + +``` +template std::unique_ptr + dynamic_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: +* The expression `static_cast((U*)0)` must be well-formed. +* `T` must have a virtual destructor. +Returns::: +* When `dynamic_cast::element_type*>(p.get())` +returns a non-zero value, `std::unique_ptr(dynamic_cast::element_type*>(p.release()));`. +* Otherwise, `std::unique_ptr()`. + +### const_pointer_cast + +``` +template T* const_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `const_cast(p)` + +``` +template std::shared_ptr + const_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::const_pointer_cast(p)` + +``` +template std::unique_ptr + const_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `const_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(const_cast::element_type*>(p.release()))`. + +### reinterpret_pointer_cast + +``` +template T* reinterpret_pointer_cast(U* p) noexcept; +``` +:: +Returns::: `reinterpret_cast(p)` + +``` +template std::shared_ptr + reinterpret_pointer_cast(const std::shared_ptr& p) noexcept; +``` +:: +Returns::: `std::reinterpret_pointer_cast(p)` + +``` +template std::unique_ptr + reinterpret_pointer_cast(std::unique_ptr&& p) noexcept; +``` +:: +Requires::: The expression `reinterpret_cast((U*)0)` must be well-formed. +Returns::: `std::unique_ptr(reinterpret_cast::element_type*>(p.release()))`. + +## Example + +The following example demonstrates how the generic pointer casts help us +create pointer independent code. + +``` +#include +#include + +class base { +public: + virtual ~base() { } +}; + +class derived : public base { }; + +template +void check_if_it_is_derived(const Ptr& ptr) +{ + assert(boost::dynamic_pointer_cast(ptr) != 0); +} + +int main() +{ + base* ptr = new derived; + boost::shared_ptr sptr(new derived); + + check_if_it_is_derived(ptr); + check_if_it_is_derived(sptr); + + delete ptr; +} +``` \ No newline at end of file diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc new file mode 100644 index 0000000..d903cad --- /dev/null +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -0,0 +1,114 @@ +//// +Copyright 2005, 2006 Ion Gaztañaga +Copyright 2005, 2006, 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#pointer_to_other] +# pointer_to_other +:toc: +:toc-title: +:idprefix: pointer_to_other_ + +## Description + +The `pointer_to_other` utility provides a way, given a source pointer type, to obtain a pointer of the same type +to another pointee type. + +There is test/example code in link:../../test/pointer_to_other_test.cpp[pointer_to_other_test.cpp]. + +## Rationale + +When building pointer independent classes, like memory managers, allocators, or containers, there is often a need to +define pointers generically, so that if a template parameter represents a pointer (for example, a raw or smart pointer +to an `int`), we can define another pointer of the same type to another pointee (a raw or smart pointer to a `float`.) + +``` +template class FloatPointerHolder +{ + // Let's define a pointer to a float + + typedef typename boost::pointer_to_other + ::type float_ptr_t; + + float_ptr_t float_ptr; +}; +``` + +## Synopsis + +`pointer_to_other` is defined in ``. + +``` +namespace boost { + + template struct pointer_to_other; + + template class Sp> + struct pointer_to_other< Sp, U > + { + typedef Sp type; + }; + + template class Sp> + struct pointer_to_other< Sp, U > + { + typedef Sp type; + }; + + template class Sp> + struct pointer_to_other< Sp, U > + { + typedef Sp type; + }; + + template + struct pointer_to_other< T*, U > + { + typedef U* type; + }; +} +``` + +If these definitions are not correct for a specific smart pointer, we can define a specialization of `pointer_to_other`. + +## Example + +``` +// Let's define a memory allocator that can +// work with raw and smart pointers + +#include + +template +class memory_allocator +{ + // Predefine a memory_block + + struct block; + + // Define a pointer to a memory_block from a void pointer + // If VoidPtr is void *, block_ptr_t is block* + // If VoidPtr is smart_ptr, block_ptr_t is smart_ptr + + typedef typename boost::pointer_to_other + ::type block_ptr_t; + + struct block + { + std::size_t size; + block_ptr_t next_block; + }; + + block_ptr_t free_blocks; +}; +``` + +As we can see, using `pointer_to_other` we can create pointer independent code. diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc new file mode 100644 index 0000000..9746a7c --- /dev/null +++ b/doc/smart_ptr/scoped_array.adoc @@ -0,0 +1,175 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2005, 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#scoped_array] +# scoped_array: Scoped Array Ownership +:toc: +:toc-title: +:idprefix: scoped_array_ + +## Description + +The `scoped_array` class template stores a pointer to a dynamically allocated array. +(Dynamically allocated arrays are allocated with the {cpp} `new[]` expression.) The array +pointed to is guaranteed to be deleted, either on destruction of the `scoped_array`, +or via an explicit `reset`. + +The `scoped_array` template 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_array` is so simple, in its usual implementation every operation is as fast as a +built-in array pointer and it has no more space overhead that a built-in array pointer. + +It cannot be used in {cpp} standard library containers. See `shared_ptr` if `scoped_array` +does not meet your needs. + +It cannot correctly hold a pointer to a single object. See `scoped_ptr` for that usage. + +`std::vector` is an alternative to `scoped_array` that is a bit heavier duty but far more flexible. +`boost::array` is an alternative that does not use dynamic allocation. + +The class template is parameterized on `T`, the type of the object pointed to. + +## Synopsis + +`scoped_array` is defined in ``. + +``` +namespace boost { + + template class scoped_array { + private: + + scoped_array(scoped_array const &); + scoped_array & operator=(scoped_array const &); + + void operator==( scoped_array const& ) const; + void operator!=( scoped_array const& ) const; + + public: + + typedef T element_type; + + explicit scoped_array(T * p = 0) noexcept; + ~scoped_array() noexcept; + + void reset(T * p = 0) noexcept; + + T & operator[](std::ptrdiff_t i) const noexcept; + T * get() const noexcept; + + explicit operator bool () const noexcept; + + void swap(scoped_array & b) noexcept; + }; + + template void swap(scoped_array & a, scoped_array & b) noexcept; + + template + bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; + template + bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + + template + bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; + template + bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; +} +``` + +## Members + +### element_type + + typedef T element_type; + +Provides the type of the stored pointer. + +### constructors + + explicit scoped_array(T * p = 0) noexcept; + +Constructs a `scoped_array`, 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_array() noexcept; + +Deletes the array pointed to by the stored pointer. Note that `delete[]` on a pointer with +a value of 0 is harmless. `T` must be complete, and `delete[]` on the stored pointer must +not throw exceptions. + +### reset + + void reset(T * p = 0) noexcept; + +Deletes the array 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. `T` must be complete, +and `delete[]` on the stored pointer must not throw exceptions. + +### subscripting + + T & operator[](std::ptrdiff_t i) const noexcept; + +Returns a reference to element `i` of the array pointed to by the stored pointer. +Behavior is undefined and almost certainly undesirable if the stored pointer is 0, +or if `i` is less than 0 or is greater than or equal to the number of elements in +the array. + +### get + + T * get() const noexcept; + +Returns the stored pointer. `T` need not be a complete type. + +### conversions + + explicit operator bool () const noexcept; + +Returns `get() != 0`. + +NOTE: On C++03 compilers, the return value is of an unspecified type. + +### swap + + void swap(scoped_array & b) noexcept; + +Exchanges the contents of the two smart pointers. `T` need not be a complete type. + +## Free Functions + +### swap + + template void swap(scoped_array & a, scoped_array & b) noexcept; + +Equivalent to `a.swap(b)`. + +### comparisons + + template + bool operator==( scoped_array const & p, std::nullptr_t ) noexcept; + + template + bool operator==( std::nullptr_t, scoped_array const & p ) noexcept; + +Returns `p.get() == nullptr`. + + template + bool operator!=( scoped_array const & p, std::nullptr_t ) noexcept; + + template + bool operator!=( std::nullptr_t, scoped_array const & p ) noexcept; + +Returns `p.get() != nullptr`. diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc new file mode 100644 index 0000000..4f08811 --- /dev/null +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -0,0 +1,234 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#scoped_ptr] +# scoped_ptr: Scoped Object Ownership +:toc: +:toc-title: +: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; + + template + bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; + template + bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; + + template + bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; + template + bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; +} +``` + +## 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`. + +NOTE: On C++03 compilers, the return value is of an unspecified type. + +### 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)`. + +### comparisons + + template bool operator==( scoped_ptr const & p, std::nullptr_t ) noexcept; + + template bool operator==( std::nullptr_t, scoped_ptr const & p ) noexcept; + +Returns `p.get() == nullptr`. + + template bool operator!=( scoped_ptr const & p, std::nullptr_t ) noexcept; + + template bool operator!=( std::nullptr_t, scoped_ptr const & p ) noexcept; + +Returns `p.get() != nullptr`. + +## 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 new file mode 100644 index 0000000..5be074c --- /dev/null +++ b/doc/smart_ptr/shared_array.adoc @@ -0,0 +1,270 @@ +//// +Copyright 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[[shared_array]] +[appendix] +# shared_array (deprecated) +:toc: +:toc-title: +:idprefix: shared_array_ + +NOTE: This facility is deprecated because a `shared_ptr` to `T[]` or `T[N]` +is now available, and is superior in every regard. + +## Description + +The `shared_array` class template stores a pointer to a dynamically allocated +array. (Dynamically allocated array are allocated with the C++ `new[]` +expression.) The object pointed to is guaranteed to be deleted when the last +`shared_array` pointing to it is destroyed or reset. + +Every `shared_array` meets the _CopyConstructible_ and _Assignable_ +requirements of the {cpp} Standard Library, and so can be used in standard +library containers. Comparison operators are supplied so that shared_array +works with the standard library's associative containers. + +Normally, a `shared_array` cannot correctly hold a pointer to an object that +has been allocated with the non-array form of `new`. See `shared_ptr` for that +usage. + +Because the implementation uses reference counting, cycles of `shared_array` +instances will not be reclaimed. For example, if `main` holds a shared_array +to `A`, which directly or indirectly holds a shared_array back to `A`, the use +count of `A` will be 2. Destruction of the original `shared_array` will leave +`A` dangling with a use count of 1. + +A `shared_ptr` to a `std::vector` is an alternative to a `shared_array` that +is a bit heavier duty but far more flexible. + +The class template is parameterized on `T`, the type of the object pointed to. +`shared_array` and most of its member functions place no requirements on `T`; +it is allowed to be an incomplete type, or `void`. Member functions that do +place additional requirements (constructors, reset) are explicitly documented +below. + +## Synopsis + +``` +namespace boost { + + template class shared_array { + public: + typedef T element_type; + + explicit shared_array(T* p = 0); + template shared_array(T* p, D d); + shared_array(const shared_array& v) noexcept; + + ~shared_array() noexcept; + + shared_array& operator=(const shared_array& v) noexcept; + + void reset(T* p = 0); + template void reset(T* p, D d); + + T& operator[](std::ptrdiff_t n) const noexcept; + T* get() const noexcept; + + bool unique() const noexcept; + long use_count() const noexcept; + + explicit operator bool() const noexcept; + + void swap(shared_array& v) noexcept; + }; + + template bool + operator==(const shared_array& a, const shared_array& b) noexcept; + template bool + operator!=(const shared_array& a, const shared_array& b) noexcept; + template bool + operator<(const shared_array& a, const shared_array& b) noexcept; + + template + void swap(shared_array& a, shared_array& b) noexcept; +} +``` + +## Members + +### element_type + +``` +typedef T element_type; +``` +Type:: Provides the type of the stored pointer. + +### Constructors + +``` +explicit shared_array(T* p = 0); +``` +:: +Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a +pointer to an array that was allocated via a C++ `new[]` expression or be 0. +Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`). +Requires::: `T` is a complete type. +Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. + +``` +template shared_array(T* p, D d); +``` +:: +Effects::: Constructs a `shared_array`, storing a copy of `p` and of `d`. +Afterwards, the use count is 1. When the the time comes to delete the array +pointed to by `p`, the object `d` is used in the statement `d(p)`. +Requires::: +* `T` is a complete type. +* The copy constructor and destructor of `D` must not throw. +* Invoking the object `d` with parameter `p` must not throw. +Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. + +``` +shared_array(const shared_array& v) noexcept; +``` +:: +Effects::: Constructs a `shared_array`, as if by storing a copy of the pointer +stored in `v`. Afterwards, the use count for all copies is 1 more than the +initial use count. +Requires::: `T` is a complete type. + +### Destructor + +``` +~shared_array() noexcept; +``` +:: +Effects::: Decrements the use count. Then, if the use count is 0, deletes the +array pointed to by the stored pointer. Note that `delete[]` on a pointer with +a value of 0 is harmless. + +### Assignment + +``` +shared_array& operator=(const shared_array& v) noexcept; +``` +:: +Effects::: Constructs a new `shared_array` as described above, then replaces +this `shared_array` with the new one, destroying the replaced object. +Requires::: `T` is a complete type. +Returns::: `*this`. + +### reset + +``` +void reset(T* p = 0); +``` +:: +Effects::: Constructs a new `shared_array` as described above, then replaces +this `shared_array` with the new one, destroying the replaced object. +Requires::: `T` is a complete type. +Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. + +``` +template void reset(T* p, D d); +``` +:: +Effects::: Constructs a new `shared_array` as described above, then replaces +this `shared_array` with the new one, destroying the replaced object. +Requires::: +* `T` is a complete type. +* The copy constructor of `D` must not throw. +Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. + +### Indexing + +``` +T& operator[](std::ptrdiff_t n) const noexcept; +``` +Returns::: A reference to element `n` of the array pointed to by the stored +pointer. Behavior is undefined and almost certainly undesirable if the stored +pointer is 0, or if `n` is less than 0 or is greater than or equal to the +number of elements in the array. +Requires::: `T` is a complete type. + +### get + +``` +T* get() const noexcept; +``` +:: +Returns::: The stored pointer. + +### unique + +``` +bool unique() const noexcept; +``` +:: +Returns::: `true` if no other `shared_array` is sharing ownership of the +stored pointer, `false` otherwise. + +### use_count + +``` +long use_count() const noexcept; +``` +:: +Returns::: The number of `shared_array` objects sharing ownership of the +stored pointer. + +### Conversions + +``` +explicit operator bool() const noexcept; +``` +:: +Returns::: `get() != 0`. +Requires::: `T` is a complete type. + +### swap + +``` +void swap(shared_array& b) noexcept; +``` +:: +Effects::: Exchanges the contents of the two smart pointers. + +## Free Functions + +### Comparison + +``` +template bool + operator==(const shared_array& a, const shared_array& b) noexcept; +``` +``` +template bool + operator!=(const shared_array& a, const shared_array& b) noexcept; +``` +``` +template bool + operator<(const shared_array& a, const shared_array& b) noexcept; +``` +:: +Returns::: The result of comparing the stored pointers of the two smart +pointers. + +NOTE: The `operator<` overload is provided to define an ordering so that +`shared_array` objects can be used in associative containers such as +`std::map`. The implementation uses `std::less` to perform the comparison. +This ensures that the comparison is handled correctly, since the standard +mandates that relational operations on pointers are unspecified (5.9 +[expr.rel] paragraph 2) but `std::less` on pointers is well-defined (20.3.3 +[lib.comparisons] paragraph 8). + +### swap + +``` +template + void swap(shared_array& a, shared_array& b) noexcept; +``` +:: +Returns::: `a.swap(b)`. +Requires::: `T` is a complete type. diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc new file mode 100644 index 0000000..594c740 --- /dev/null +++ b/doc/smart_ptr/shared_ptr.adoc @@ -0,0 +1,934 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#shared_ptr] +# shared_ptr: Shared Ownership +:toc: +:toc-title: +:idprefix: shared_ptr_ + +## Description + +The `shared_ptr` class template stores a pointer to a dynamically allocated object, typically with a {cpp} `new`-expression. +The object pointed to is guaranteed to be deleted when the last `shared_ptr` pointing to it is destroyed or reset. + +.Using shared_ptr +``` +shared_ptr p1( new X ); +shared_ptr p2( new int(5) ); +``` + +`shared_ptr` deletes the exact pointer that has been passed at construction time, complete with its original type, regardless +of the template parameter. In the second example above, when `p2` is destroyed or reset, it will call `delete` on the original +`int*` that has been passed to the constructor, even though `p2` itself is of type `shared_ptr` and stores a pointer of +type `void*`. + +Every `shared_ptr` meets the `CopyConstructible`, `MoveConstructible`, `CopyAssignable` and `MoveAssignable` requirements of the +{cpp} Standard Library, and can be used in standard library containers. Comparison operators are supplied so that `shared_ptr` +works with the standard library's associative containers. + +Because the implementation uses reference counting, cycles of `shared_ptr` instances will not be reclaimed. For example, if `main()` +holds a `shared_ptr` to `A`, which directly or indirectly holds a `shared_ptr` back to `A`, `A`'s use count will be 2. Destruction +of the original `shared_ptr` will leave `A` dangling with a use count of 1. Use `<>` to "break cycles." + +The class template is parameterized on `T`, the type of the object pointed to. `shared_ptr` and most of its member functions place +no requirements on `T`; it is allowed to be an incomplete type, or `void`. Member functions that do place additional requirements +(constructors, `reset`) are explicitly documented below. + +`shared_ptr` can be implicitly converted to `shared_ptr` whenever `T*` can be implicitly converted to `U*`. In particular, +`shared_ptr` is implicitly convertible to `shared_ptr`, to `shared_ptr` where `U` is an accessible base of `T`, +and to `shared_ptr`. + +`shared_ptr` is now part of the C++11 Standard, as `std::shared_ptr`. + +Starting with Boost release 1.53, `shared_ptr` can be used to hold a pointer to a dynamically allocated array. This is accomplished +by using an array type (`T[]` or `T[N]`) as the template parameter. There is almost no difference between using an unsized array, +`T[]`, and a sized array, `T[N]`; the latter just enables `operator[]` to perform a range check on the index. + +.Using shared_ptr with arrays +``` +shared_ptr p1( new double[1024] ); +shared_ptr p2( new double[n] ); +``` + +## Best Practices + +A simple guideline that nearly eliminates the possibility of memory leaks is: always use a named smart pointer variable to hold the result +of `new`. Every occurence of the `new` keyword in the code should have the form: + + shared_ptr p(new Y); + +It is, of course, acceptable to use another smart pointer in place of `shared_ptr` above; having `T` and `Y` be the same type, or passing +arguments to the constructor of `Y` is also OK. + +If you observe this guideline, it naturally follows that you will have no explicit `delete` statements; `try`/`catch` constructs will be rare. + +Avoid using unnamed `shared_ptr` temporaries to save typing; to see why this is dangerous, consider this example: + +.Exception-safe and -unsafe use of shared_ptr +``` +void f(shared_ptr, int); +int g(); + +void ok() +{ + shared_ptr p( new int(2) ); + f( p, g() ); +} + +void bad() +{ + f( shared_ptr( new int(2) ), g() ); +} +``` + +The function `ok` follows the guideline to the letter, whereas `bad` constructs the temporary `shared_ptr` in place, admitting the possibility of +a memory leak. Since function arguments are evaluated in unspecified order, it is possible for `new int(2)` to be evaluated first, `g()` second, +and we may never get to the `shared_ptr` constructor if `g` throws an exception. See http://www.gotw.ca/gotw/056.htm[Herb Sutter's treatment] of +the issue for more information. + +The exception safety problem described above may also be eliminated by using the `<>` or `allocate_shared` factory +functions defined in ``. These factory functions also provide an efficiency benefit by consolidating allocations. + +## Synopsis + +`shared_ptr` is defined in ``. + +``` +namespace boost { + + class bad_weak_ptr: public std::exception; + + template class weak_ptr; + + template class shared_ptr { + public: + + typedef /*see below*/ element_type; + + shared_ptr() noexcept; + shared_ptr(std::nullptr_t) noexcept; + + template explicit shared_ptr(Y * p); + template shared_ptr(Y * p, D d); + template shared_ptr(Y * p, D d, A a); + template shared_ptr(std::nullptr_t p, D d); + template shared_ptr(std::nullptr_t p, D d, A a); + + ~shared_ptr() noexcept; + + shared_ptr(shared_ptr const & r) noexcept; + template shared_ptr(shared_ptr const & r) noexcept; + + shared_ptr(shared_ptr && r) noexcept; + template shared_ptr(shared_ptr && r) noexcept; + + template shared_ptr(shared_ptr const & r, element_type * p) noexcept; + + template shared_ptr(shared_ptr && r, element_type * p) noexcept; + + template explicit shared_ptr(weak_ptr const & r); + + template explicit shared_ptr(std::auto_ptr & r); + template shared_ptr(std::auto_ptr && r); + + template shared_ptr(std::unique_ptr && r); + + shared_ptr & operator=(shared_ptr const & r) noexcept; + template shared_ptr & operator=(shared_ptr const & r) noexcept; + + shared_ptr & operator=(shared_ptr const && r) noexcept; + template shared_ptr & operator=(shared_ptr const && r) noexcept; + + template shared_ptr & operator=(std::auto_ptr & r); + template shared_ptr & operator=(std::auto_ptr && r); + + template shared_ptr & operator=(std::unique_ptr && r); + + shared_ptr & operator=(std::nullptr_t) noexcept; + + void reset() noexcept; + + template void reset(Y * p); + template void reset(Y * p, D d); + template void reset(Y * p, D d, A a); + + template void reset(shared_ptr const & r, element_type * p) noexcept; + + T & operator*() const noexcept; // only valid when T is not an array type + T * operator->() const noexcept; // only valid when T is not an array type + + // only valid when T is an array type + element_type & operator[](std::ptrdiff_t i) const noexcept; + + element_type * get() const noexcept; + + bool unique() const noexcept; + long use_count() const noexcept; + + explicit operator bool() const noexcept; + + void swap(shared_ptr & b) noexcept; + + template bool owner_before(shared_ptr const & rhs) const noexcept; + template bool owner_before(weak_ptr const & rhs) const noexcept; + }; + + template + bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; + + template + bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; + + template + bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; + + template bool operator==(shared_ptr const & p, std::nullptr_t) noexcept; + template bool operator==(std::nullptr_t, shared_ptr const & p) noexcept; + + template bool operator!=(shared_ptr const & p, std::nullptr_t) noexcept; + template bool operator!=(std::nullptr_t, shared_ptr const & p) noexcept; + + template void swap(shared_ptr & a, shared_ptr & b) noexcept; + + template + typename shared_ptr::element_type * + get_pointer(shared_ptr const & p) noexcept; + + template + shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; + + template + shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; + + template + shared_ptr dynamic_pointer_cast(shared_ptr const & r) noexcept; + + template + shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; + + template + std::basic_ostream & + operator<< (std::basic_ostream & os, shared_ptr const & p); + + template D * get_deleter(shared_ptr const & p) noexcept; +} +``` + +## Members + +### element_type +``` +typedef ... element_type; +``` +`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. + +### default constructor +``` +shared_ptr() noexcept; +``` +``` +shared_ptr(std::nullptr_t) noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs an empty `shared_ptr`. +Postconditions:: `use_count() == 0 && get() == 0`. + +### pointer constructor +``` +template explicit shared_ptr(Y * p); +``` +[none] +* {blank} ++ +Requires:: `Y` must be a complete type. The expression `delete[] p`, when `T` is an array type, or `delete p`, when `T` is not an array type, + must be well-formed, well-defined, and not throw exceptions. When `T` is `U[N]`, `Y(\*)[N]` must be convertible to `T*`; when `T` is `U[]`, `Y(\*)[]` + must be convertible to `T*`; otherwise, `Y\*` must be convertible to `T*`. + +Effects:: When `T` is not an array type, constructs a `shared_ptr` that owns the pointer `p`. Otherwise, constructs a `shared_ptr` that owns `p` and + a deleter of an unspecified type that calls `delete[] p`. + +Postconditions:: `use_count() == 1 && get() == p`. If `T` is not an array type and `p` is unambiguously convertible to `enable_shared_from_this*` + for some `V`, `p\->shared_from_this()` returns a copy of `*this`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, the constructor calls `delete[] p`, when `T` is an array type, or `delete p`, when `T` is not an array type. + +NOTE: `p` must be a pointer to an object that was allocated via a {cpp} `new` expression or be 0. The postcondition that use count is 1 holds even if `p` +is 0; invoking `delete` on a pointer that has a value of 0 is harmless. + +NOTE: This constructor is a template in order to remember the actual pointer type passed. The destructor will call delete with the same pointer, complete +with its original type, even when `T` does not have a virtual destructor, or is `void`. + +### constructors taking a deleter +``` +template shared_ptr(Y * p, D d); +``` +``` +template shared_ptr(Y * p, D d, A a); +``` +``` +template shared_ptr(std::nullptr_t p, D d); +``` +``` +template shared_ptr(std::nullptr_t p, D d, A a); +``` +[none] +* {blank} ++ +Requires:: `D` must be `CopyConstructible`. The copy constructor and destructor of `D` must not throw. The expression `d(p)` must be well-formed, well-defined, + and not throw exceptions. `A` must be an `Allocator`, as described in section Allocator Requirements [allocator.requirements] of the {cpp} Standard. + When `T` is `U[N]`, `Y(\*)[N]` must be convertible to `T*`; when `T` is `U[]`, `Y(\*)[]` must be convertible to `T*`; otherwise, `Y\*` must be convertible to `T*`. + +Effects:: Constructs a `shared_ptr` that owns the pointer `p` and the deleter `d`. The constructors taking an allocator a allocate memory using a copy of `a`. + +Postconditions:: `use_count() == 1 && get() == p`. If `T` is not an array type and `p` is unambiguously convertible to `enable_shared_from_this*` for some `V`, + `p\->shared_from_this()` returns a copy of `*this`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, `d(p)` is called. + +NOTE: When the the time comes to delete the object pointed to by `p`, the stored copy of `d` is invoked with the stored copy of `p` as an argument. + +NOTE: Custom deallocators allow a factory function returning a `shared_ptr` to insulate the user from its memory allocation strategy. Since the deallocator +is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation. For example, +a "no-op" deallocator is useful when returning a `shared_ptr` to a statically allocated object, and other variations allow a `shared_ptr` to be used as a wrapper +for another smart pointer, easing interoperability. + +NOTE: The requirement that the copy constructor of `D` does not throw comes from the pass by value. If the copy constructor throws, the pointer would leak. + +### copy and converting constructors +``` +shared_ptr(shared_ptr const & r) noexcept; +``` +``` +template shared_ptr(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: If `r` is empty, constructs an empty `shared_ptr`; otherwise, constructs a `shared_ptr` that shares ownership with `r`. + +Postconditions:: `get() == r.get() && use_count() == r.use_count()`. + +### move constructors +``` +shared_ptr(shared_ptr && r) noexcept; +``` +``` +template shared_ptr(shared_ptr && r) noexcept; +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Move-constructs a `shared_ptr` from `r`. + +Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`. + +### aliasing constructor +``` +template shared_ptr(shared_ptr const & r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: constructs a shared_ptr that shares ownership with r and stores p. + +Postconditions:: `get() == p && use_count() == r.use_count()`. + +### aliasing move constructor +``` +template shared_ptr(shared_ptr && r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: Move-constructs a `shared_ptr` from `r`, while storing `p` instead. + +Postconditions:: `get() == p` and `use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`. + +### weak_ptr constructor +``` +template explicit shared_ptr(weak_ptr const & r); +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Constructs a `shared_ptr` that shares ownership with `r` and stores a copy of the pointer stored in `r`. + +Postconditions:: `use_count() == r.use_count()`. + +Throws:: `bad_weak_ptr` when `r.use_count() == 0`. + +Exception safety:: If an exception is thrown, the constructor has no effect. + +### auto_ptr constructors +``` +template shared_ptr(std::auto_ptr & r); +``` +``` +template shared_ptr(std::auto_ptr && r); +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: Constructs a `shared_ptr`, as if by storing a copy of `r.release()`. + +Postconditions:: `use_count() == 1`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, the constructor has no effect. + +### unique_ptr constructor +``` +template shared_ptr(std::unique_ptr && r); +``` +[none] +* {blank} ++ +Requires:: `Y*` should be convertible to `T*`. + +Effects:: +- When `r.get() == 0`, equivalent to `shared_ptr()`; +- When `D` is not a reference type, equivalent to `shared_ptr(r.release(), r.get_deleter())`; +- Otherwise, equivalent to `shared_ptr(r.release(), del)`, where `del` is a deleter that stores the reference `rd` returned + from `r.get_deleter()` and `del(p)` calls `rd(p)`. + +Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained. + +Exception safety:: If an exception is thrown, the constructor has no effect. + +### destructor +``` +~shared_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: +- If `*this` is empty, or shares ownership with another `shared_ptr` instance (`use_count() > 1`), there are no side effects. +- Otherwise, if `*this` owns a pointer `p` and a deleter `d`, `d(p)` is called. +- Otherwise, `*this` owns a pointer `p`, and `delete p` is called. + +### assignment +``` +shared_ptr & operator=(shared_ptr const & r) noexcept; +``` +``` +template shared_ptr & operator=(shared_ptr const & r) noexcept; +``` +``` +template shared_ptr & operator=(std::auto_ptr & r); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(r).swap(*this)`. +Returns:: `*this`. + +NOTE: The use count updates caused by the temporary object construction and destruction are not considered observable side effects, +and the implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. + +[NOTE] +==== +In particular, in the example: +``` +shared_ptr p(new int); +shared_ptr q(p); +p = p; +q = p; +``` +both assignments may be no-ops. +==== + +``` +shared_ptr & operator=(shared_ptr && r) noexcept; +``` +``` +template shared_ptr & operator=(shared_ptr && r) noexcept; +``` +``` +template shared_ptr & operator=(std::auto_ptr && r); +``` +``` +template shared_ptr & operator=(std::unique_ptr && r); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(std::move(r)).swap(*this)`. +Returns:: `*this`. + +``` +shared_ptr & operator=(std::nullptr_t) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr().swap(*this)`. +Returns:: `*this`. + +### reset +``` +void reset() noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr().swap(*this)`. + +``` +template void reset(Y * p); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(p).swap(*this)`. + +``` +template void reset(Y * p, D d); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(p, d).swap(*this)`. + +``` +template void reset(Y * p, D d, A a); +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(p, d, a).swap(*this)`. + +``` +template void reset(shared_ptr const & r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(r, p).swap(*this)`. + +``` +template void reset(shared_ptr && r, element_type * p) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `shared_ptr(std::move(r), p).swap(*this)`. + +### indirection +``` +T & operator*() const noexcept; +``` +[none] +* {blank} ++ +Requires:: `T` should not be an array type. The stored pointer must not be 0. +Returns:: `*get()`. + +``` +T * operator->() const noexcept; +``` +[none] +* {blank} ++ +Requires:: `T` should not be an array type. The stored pointer must not be 0. +Returns:: `get()`. + +``` +element_type & operator[](std::ptrdiff_t i) const noexcept; +``` +[none] +* {blank} ++ +Requires:: `T` should be an array type. The stored pointer must not be 0. `i >= 0`. If `T` is `U[N]`, `i < N`. +Returns:: `get()[i]`. + +### get + +``` +element_type * get() const noexcept; +``` +[none] +* {blank} ++ +Returns:: The stored pointer. + +### unique +``` +bool unique() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `use_count() == 1`. + +### use_count +``` +long use_count() const noexcept; +``` +[none] +* {blank} ++ +Returns:: The number of `shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. + +### conversions +``` +explicit operator bool() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `get() != 0`. + +NOTE: This conversion operator allows `shared_ptr` objects to be used in boolean contexts, like `if(p && p\->valid()) {}`. + +NOTE: The conversion to `bool` is not merely syntactic sugar. It allows `shared_ptr` variables to be declared in conditions when using +`dynamic_pointer_cast` or `weak_ptr::lock`. + +NOTE: On C++03 compilers, the return value is of an unspecified type. + +### swap +``` +void swap(shared_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +### owner_before +``` +template bool owner_before(shared_ptr const & rhs) const noexcept; +``` +``` +template bool owner_before(weak_ptr const & rhs) const noexcept; +``` +[none] +* {blank} ++ +Effects:: See the description of `operator<`. + +## Free Functions + +### comparison +``` +template + bool operator==(shared_ptr const & a, shared_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: `a.get() == b.get()`. + +``` +template + bool operator!=(shared_ptr const & a, shared_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: `a.get() != b.get()`. + +``` +template bool operator==(shared_ptr const & p, std::nullptr_t) noexcept; +``` +``` +template bool operator==(std::nullptr_t, shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: `p.get() == 0`. + +``` +template bool operator!=(shared_ptr const & p, std::nullptr_t) noexcept; +``` +``` +template bool operator!=(std::nullptr_t, shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: `p.get() != 0`. + +``` +template + bool operator<(shared_ptr const & a, shared_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: An unspecified value such that + - `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; + - under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `shared_ptr` instances + are equivalent if and only if they share ownership or are both empty. + +NOTE: Allows `shared_ptr` objects to be used as keys in associative containers. + +NOTE: The rest of the comparison operators are omitted by design. + +### swap +``` +template void swap(shared_ptr & a, shared_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +### get_pointer +``` +template + typename shared_ptr::element_type * + get_pointer(shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: `p.get()`. + +NOTE: Provided as an aid to generic programming. Used by `mem_fn`. + +### static_pointer_cast +``` +template + shared_ptr static_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `static_cast( (U*)0 )` must be well-formed. +Returns:: `shared_ptr( r, static_cast::element_type*>(r.get()) )`. + +CAUTION: The seemingly equivalent expression `shared_ptr(static_cast(r.get()))` will eventually +result in undefined behavior, attempting to delete the same object twice. + +### const_pointer_cast +``` +template + shared_ptr const_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `const_cast( (U*)0 )` must be well-formed. +Returns:: `shared_ptr( r, const_cast::element_type*>(r.get()) )`. + +### dynamic_pointer_cast +``` +template + shared_ptr dynamic_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `dynamic_cast( (U*)0 )` must be well-formed. +Returns:: + - When `dynamic_cast::element_type*>(r.get())` returns a nonzero value `p`, `shared_ptr(r, p)`; + - Otherwise, `shared_ptr()`. + +### reinterpret_pointer_cast +``` +template + shared_ptr reinterpret_pointer_cast(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Requires:: The expression `reinterpret_cast( (U*)0 )` must be well-formed. +Returns:: `shared_ptr( r, reinterpret_cast::element_type*>(r.get()) )`. + +### operator<< +``` +template + std::basic_ostream & + operator<< (std::basic_ostream & os, shared_ptr const & p); +``` +[none] +* {blank} ++ +Effects:: `os << p.get();`. +Returns:: `os`. + +### get_deleter +``` +template + D * get_deleter(shared_ptr const & p) noexcept; +``` +[none] +* {blank} ++ +Returns:: If `*this` owns a deleter `d` of type (cv-unqualified) `D`, returns `&d`; otherwise returns 0. + +## Example + +See link:../../example/shared_ptr_example.cpp[shared_ptr_example.cpp] for a complete example program. The program builds a +`std::vector` and `std::set` of `shared_ptr` objects. + +Note that after the containers have been populated, some of the `shared_ptr` objects will have a use count of 1 rather than +a use count of 2, since the set is a `std::set` rather than a `std::multiset`, and thus does not contain duplicate entries. +Furthermore, the use count may be even higher at various times while `push_back` and `insert` container operations are performed. +More complicated yet, the container operations may throw exceptions under a variety of circumstances. Getting the memory management +and exception handling in this example right without a smart pointer would be a nightmare. + +## Handle/Body Idiom + +One common usage of `shared_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) +in the header file. + +The link:../../example/shared_ptr_example2_test.cpp[shared_ptr_example2_test.cpp] sample program includes a header file, +link:../../example/shared_ptr_example2.hpp[shared_ptr_example2.hpp], which uses a `shared_ptr` to an incomplete type to hide the implementation. +The instantiation of member functions which require a complete type occurs in the link:../../example/shared_ptr_example2.cpp[shared_ptr_example2.cpp] +implementation file. Note that there is no need for an explicit destructor. Unlike `~scoped_ptr`, `~shared_ptr` does not require that `T` be a complete type. + +## Thread Safety + +`shared_ptr` objects offer the same level of thread safety as built-in types. A `shared_ptr` instance can be "read" (accessed using only const operations) +simultaneously by multiple threads. Different `shared_ptr` instances can be "written to" (accessed using mutable operations such as `operator=` or `reset`) +simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.) + +Any other simultaneous accesses result in undefined behavior. + +Examples: +``` +shared_ptr p(new int(42)); +``` + +.Reading a `shared_ptr` from two threads +``` +// thread A +shared_ptr p2(p); // reads p + +// thread B +shared_ptr p3(p); // OK, multiple reads are safe +``` + +.Writing different `shared_ptr` instances from two threads +``` +// thread A +p.reset(new int(1912)); // writes p + +// thread B +p2.reset(); // OK, writes p2 +``` + +.Reading and writing a `shared_ptr` from two threads +``` +// thread A +p = p3; // reads p3, writes p + +// thread B +p3.reset(); // writes p3; undefined, simultaneous read/write +``` + +.Reading and destroying a `shared_ptr` from two threads +``` +// thread A +p3 = p2; // reads p2, writes p3 + +// thread B +// p2 goes out of scope: undefined, the destructor is considered a "write access" +``` + +.Writing a `shared_ptr` from two threads +``` +// thread A +p3.reset(new int(1)); + +// thread B +p3.reset(new int(2)); // undefined, multiple writes +``` + +Starting with Boost release 1.33.0, `shared_ptr` uses a lock-free implementation on most common platforms. + +If your program is single-threaded and does not link to any libraries that might have used `shared_ptr` in its default configuration, +you can `#define` the macro `BOOST_SP_DISABLE_THREADS` on a project-wide basis to switch to ordinary non-atomic reference count updates. + +(Defining `BOOST_SP_DISABLE_THREADS` in some, but not all, translation units is technically a violation of the One Definition Rule and +undefined behavior. Nevertheless, the implementation attempts to do its best to accommodate the request to use non-atomic updates in those +translation units. No guarantees, though.) + +You can define the macro `BOOST_SP_USE_PTHREADS` to turn off the lock-free platform-specific implementation and fall back to the generic +`pthread_mutex_t`-based code. + +## Frequently Asked Questions + +[qanda] +There are several variations of shared pointers, with different tradeoffs; why does the smart pointer library supply only a single implementation? It would be useful to be able to experiment with each type so as to find the most suitable for the job at hand?:: + + An important goal of `shared_ptr` is to provide a standard shared-ownership pointer. Having a single pointer type is important for stable + library interfaces, since different shared pointers typically cannot interoperate, i.e. a reference counted pointer (used by library A) + cannot share ownership with a linked pointer (used by library B.) + +Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?:: + + Parameterization discourages users. The `shared_ptr` template is carefully crafted to meet common needs without extensive parameterization. + +I am not convinced. Default parameters can be used where appropriate to hide the complexity. Again, why not policies?:: + + Template parameters affect the type. See the answer to the first question above. + +Why doesn't `shared_ptr` use a linked list implementation?:: + + A linked list implementation does not offer enough advantages to offset the added cost of an extra pointer. In addition, it is expensive to + make a linked list implementation thread safe. + +Why doesn't `shared_ptr` (or any of the other Boost smart pointers) supply an automatic conversion to T*?:: + + Automatic conversion is believed to be too error prone. + +Why does `shared_ptr` supply `use_count()`?:: + + As an aid to writing test cases and debugging displays. One of the progenitors had `use_count()`, and it was useful in tracking down bugs in + a complex project that turned out to have cyclic-dependencies. + +Why doesn't `shared_ptr` specify complexity requirements?:: + + Because complexity requirements limit implementors and complicate the specification without apparent benefit to `shared_ptr` users. For example, + error-checking implementations might become non-conforming if they had to meet stringent complexity requirements. + +Why doesn't `shared_ptr` provide a `release()` function?:: + + `shared_ptr` cannot give away ownership unless it's `unique()` because the other copy will still destroy the object. ++ +Consider: ++ +``` +shared_ptr a(new int); +shared_ptr b(a); // a.use_count() == b.use_count() == 2 + +int * p = a.release(); + +// Who owns p now? b will still call delete on it in its destructor. +``` ++ +Furthermore, the pointer returned by `release()` would be difficult to deallocate reliably, as the source `shared_ptr` could have been created with a +custom deleter, or may have pointed to an object of a different type. + +Why is `operator\->()` const, but its return value is a non-const pointer to the element type?:: + + Shallow copy pointers, including raw pointers, typically don't propagate constness. It makes little sense for them to do so, as you can always obtain a + non-const pointer from a const one and then proceed to modify the object through it. `shared_ptr` is "as close to raw pointers as possible but no closer". diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc new file mode 100644 index 0000000..f6da9f6 --- /dev/null +++ b/doc/smart_ptr/techniques.adoc @@ -0,0 +1,768 @@ +//// +Copyright 2003, 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[[techniques]] +[appendix] +# Smart Pointer Programming Techniques +:toc: +:toc-title: +:idprefix: techniques_ + +[#techniques_incomplete] +## Using incomplete classes for implementation hiding + +A proven technique (that works in C, too) for separating interface from implementation is to use a pointer to an incomplete class as an opaque handle: + +``` +class FILE; + +FILE * fopen(char const * name, char const * mode); +void fread(FILE * f, void * data, size_t size); +void fclose(FILE * f); +``` + + +It is possible to express the above interface using `shared_ptr`, eliminating the need to manually call `fclose`: + +``` +class FILE; + +shared_ptr fopen(char const * name, char const * mode); +void fread(shared_ptr f, void * data, size_t size); +``` + +This technique relies on `shared_ptr`’s ability to execute a custom deleter, eliminating the explicit call to `fclose`, and on the fact that `shared_ptr` can be copied and destroyed when `X` is incomplete. + +## The "Pimpl" idiom + +A {cpp} specific variation of the incomplete class pattern is the "Pimpl" idiom. The incomplete class is not exposed to the user; it is hidden behind a forwarding facade. `shared_ptr` can be used to implement a "Pimpl": + +``` +// file.hpp: + +class file +{ +private: + + class impl; + shared_ptr pimpl_; + +public: + + file(char const * name, char const * mode); + + // compiler generated members are fine and useful + + void read(void * data, size_t size); +}; + +// file.cpp: + +#include "file.hpp" + +class file::impl +{ +private: + + impl(impl const &); + impl & operator=(impl const &); + + // private data + +public: + + impl(char const * name, char const * mode) { ... } + ~impl() { ... } + void read(void * data, size_t size) { ... } +}; + +file::file(char const * name, char const * mode): pimpl_(new impl(name, mode)) +{ +} + +void file::read(void * data, size_t size) +{ + pimpl_->read(data, size); +} +``` + +The key thing to note here is that the compiler-generated copy constructor, assignment operator, and destructor all have a sensible meaning. As a result, `file` is `CopyConstructible` and `Assignable`, allowing its use in standard containers. + +## Using abstract classes for implementation hiding + +Another widely used C++ idiom for separating inteface and implementation is to use abstract base classes and factory functions. +The abstract classes are sometimes called "interfaces" and the pattern is known as "interface-based programming". Again, +`shared_ptr` can be used as the return type of the factory functions: + +``` +// X.hpp: + +class X +{ +public: + + virtual void f() = 0; + virtual void g() = 0; + +protected: + + ~X() {} +}; + +shared_ptr createX(); + +// X.cpp: + +class X_impl: public X +{ +private: + + X_impl(X_impl const &); + X_impl & operator=(X_impl const &); + +public: + + virtual void f() + { + // ... + } + + virtual void g() + { + // ... + } +}; + +shared_ptr createX() +{ + shared_ptr px(new X_impl); + return px; +} +``` + +A key property of `shared_ptr` is that the allocation, construction, deallocation, and destruction details are captured at the point of construction, inside the factory function. + +Note the protected and nonvirtual destructor in the example above. The client code cannot, and does not need to, delete a pointer to `X`; the `shared_ptr` instance returned from `createX` will correctly call `~X_impl`. + +## Preventing `delete px.get()` + +It is often desirable to prevent client code from deleting a pointer that is being managed by `shared_ptr`. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter: + +``` +class X +{ +private: + + ~X(); + + class deleter; + friend class deleter; + + class deleter + { + public: + + void operator()(X * p) { delete p; } + }; + +public: + + static shared_ptr create() + { + shared_ptr px(new X, X::deleter()); + return px; + } +}; +``` + +## Encapsulating allocation details, wrapping factory functions + +`shared_ptr` can be used in creating {cpp} wrappers over existing C style library interfaces that return raw pointers from their factory functions +to encapsulate allocation details. As an example, consider this interface, where `CreateX` might allocate `X` from its own private heap, `~X` may +be inaccessible, or `X` may be incomplete: + + X * CreateX(); + void DestroyX(X *); + +The only way to reliably destroy a pointer returned by `CreateX` is to call `DestroyX`. + +Here is how a `shared_ptr`-based wrapper may look like: + + shared_ptr createX() + { + shared_ptr px(CreateX(), DestroyX); + return px; + } + +Client code that calls `createX` still does not need to know how the object has been allocated, but now the destruction is automatic. + +[#techniques_static] +## Using a shared_ptr to hold a pointer to a statically allocated object + +Sometimes it is desirable to create a `shared_ptr` to an already existing object, so that the `shared_ptr` does not attempt to destroy the +object when there are no more references left. As an example, the factory function: + + shared_ptr createX(); + +in certain situations may need to return a pointer to a statically allocated `X` instance. + +The solution is to use a custom deleter that does nothing: + +``` +struct null_deleter +{ + void operator()(void const *) const + { + } +}; + +static X x; + +shared_ptr createX() +{ + shared_ptr px(&x, null_deleter()); + return px; +} +``` + +The same technique works for any object known to outlive the pointer. + +## Using a shared_ptr to hold a pointer to a COM Object + +Background: COM objects have an embedded reference count and two member functions that manipulate it. `AddRef()` increments the count. +`Release()` decrements the count and destroys itself when the count drops to zero. + +It is possible to hold a pointer to a COM object in a `shared_ptr`: + + shared_ptr make_shared_from_COM(IWhatever * p) + { + p->AddRef(); + shared_ptr pw(p, mem_fn(&IWhatever::Release)); + return pw; + } + +Note, however, that `shared_ptr` copies created from `pw` will not "register" in the embedded count of the COM object; +they will share the single reference created in `make_shared_from_COM`. Weak pointers created from `pw` will be invalidated when the last +`shared_ptr` is destroyed, regardless of whether the COM object itself is still alive. + +As link:../../libs/bind/mem_fn.html#Q3[explained] in the `mem_fn` documentation, you need to `#define BOOST_MEM_FN_ENABLE_STDCALL` first. + +[#techniques_intrusive] +## Using a shared_ptr to hold a pointer to an object with an embedded reference count + +This is a generalization of the above technique. The example assumes that the object implements the two functions required by `<>`, +`intrusive_ptr_add_ref` and `intrusive_ptr_release`: + +``` +template struct intrusive_deleter +{ + void operator()(T * p) + { + if(p) intrusive_ptr_release(p); + } +}; + +shared_ptr make_shared_from_intrusive(X * p) +{ + if(p) intrusive_ptr_add_ref(p); + shared_ptr px(p, intrusive_deleter()); + return px; +} +``` + +## Using a shared_ptr to hold another shared ownership smart pointer + +One of the design goals of `shared_ptr` is to be used in library interfaces. It is possible to encounter a situation where a library takes a +`shared_ptr` argument, but the object at hand is being managed by a different reference counted or linked smart pointer. + +It is possible to exploit `shared_ptr`’s custom deleter feature to wrap this existing smart pointer behind a `shared_ptr` facade: + +``` +template struct smart_pointer_deleter +{ +private: + + P p_; + +public: + + smart_pointer_deleter(P const & p): p_(p) + { + } + + void operator()(void const *) + { + p_.reset(); + } + + P const & get() const + { + return p_; + } +}; + +shared_ptr make_shared_from_another(another_ptr qx) +{ + shared_ptr px(qx.get(), smart_pointer_deleter< another_ptr >(qx)); + return px; +} +``` + +One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that `p_.reset()` doesn't throw. +If this is not the case, `p_.reset();` should be wrapped in a `try {} catch(...) {}` block that ignores exceptions. In the (usually unlikely) event +when an exception is thrown and ignored, `p_` will be released when the lifetime of the deleter ends. This happens when all references, including +weak pointers, are destroyed or reset. + +Another twist is that it is possible, given the above `shared_ptr` instance, to recover the original smart pointer, using `<>`: + +``` +void extract_another_from_shared(shared_ptr px) +{ + typedef smart_pointer_deleter< another_ptr > deleter; + + if(deleter const * pd = get_deleter(px)) + { + another_ptr qx = pd->get(); + } + else + { + // not one of ours + } +} +``` + +[#techniques_from_raw] +## Obtaining a shared_ptr from a raw pointer + +Sometimes it is necessary to obtain a `shared_ptr` given a raw pointer to an object that is already managed by another `shared_ptr` instance. Example: + + void f(X * p) + { + shared_ptr px(???); + } + +Inside `f`, we'd like to create a `shared_ptr` to `*p`. + +In the general case, this problem has no solution. One approach is to modify `f` to take a `shared_ptr`, if possible: + + void f(shared_ptr px); + +The same transformation can be used for nonvirtual member functions, to convert the implicit `this`: + + void X::f(int m); + +would become a free function with a `shared_ptr` first argument: + + void f(shared_ptr this_, int m); + +If `f` cannot be changed, but `X` uses intrusive counting, use `<>` described above. Or, if it's known that the `shared_ptr` created in `f` will never outlive the object, use <>. + +## Obtaining a shared_ptr (weak_ptr) to this in a constructor + +Some designs require objects to register themselves on construction with a central authority. When the registration routines take a `shared_ptr`, this leads to the question how could a constructor obtain a `shared_ptr` to `this`: + +``` +class X +{ +public: + + X() + { + shared_ptr this_(???); + } +}; +``` + +In the general case, the problem cannot be solved. The `X` instance being constructed can be an automatic variable or a static variable; it can be created on the heap: + + shared_ptr px(new X); + +but at construction time, `px` does not exist yet, and it is impossible to create another `shared_ptr` instance that shares ownership with it. + +Depending on context, if the inner `shared_ptr this_` doesn't need to keep the object alive, use a `null_deleter` as explained <> and <>. +If `X` is supposed to always live on the heap, and be managed by a `shared_ptr`, use a static factory function: + +``` +class X +{ +private: + + X() { ... } + +public: + + static shared_ptr create() + { + shared_ptr px(new X); + // use px as 'this_' + return px; + } +}; +``` + +## Obtaining a shared_ptr to this + +Sometimes it is needed to obtain a `shared_ptr` from `this` in a virtual member function under the assumption that `this` is already managed by a `shared_ptr`. +The transformations <> cannot be applied. + +A typical example: + +``` +class X +{ +public: + + virtual void f() = 0; + +protected: + + ~X() {} +}; + +class Y +{ +public: + + virtual shared_ptr getX() = 0; + +protected: + + ~Y() {} +}; + +// -- + +class impl: public X, public Y +{ +public: + + impl() { ... } + + virtual void f() { ... } + + virtual shared_ptr getX() + { + shared_ptr px(???); + return px; + } +}; +``` + +The solution is to keep a weak pointer to `this` as a member in `impl`: + +``` +class impl: public X, public Y +{ +private: + + weak_ptr weak_this; + + impl(impl const &); + impl & operator=(impl const &); + + impl() { ... } + +public: + + static shared_ptr create() + { + shared_ptr pi(new impl); + pi->weak_this = pi; + return pi; + } + + virtual void f() { ... } + + virtual shared_ptr getX() + { + shared_ptr px(weak_this); + return px; + } +}; +``` + +The library now includes a helper class template `<>` that can be used to encapsulate the solution: + +``` +class impl: public X, public Y, public enable_shared_from_this +{ +public: + + impl(impl const &); + impl & operator=(impl const &); + +public: + + virtual void f() { ... } + + virtual shared_ptr getX() + { + return shared_from_this(); + } +} +``` + +Note that you no longer need to manually initialize the `weak_ptr` member in `enable_shared_from_this`. Constructing a `shared_ptr` to `impl` takes care of that. + +## Using shared_ptr as a smart counted handle + +Some library interfaces use opaque handles, a variation of the <> described above. An example: + +``` +typedef void * HANDLE; + +HANDLE CreateProcess(); +void CloseHandle(HANDLE); +``` + +Instead of a raw pointer, it is possible to use `shared_ptr` as the handle and get reference counting and automatic resource management for free: + +``` +typedef shared_ptr handle; + +handle createProcess() +{ + shared_ptr pv(CreateProcess(), CloseHandle); + return pv; +} +``` + +## Using shared_ptr to execute code on block exit + +`shared_ptr` can automatically execute cleanup code when control leaves a scope. + +* Executing `f(p)`, where `p` is a pointer: ++ +``` +shared_ptr guard(p, f); +``` + +* Executing arbitrary code: `f(x, y)`: ++ +``` +shared_ptr guard(static_cast(0), bind(f, x, y)); +``` + +## Using shared_ptr to hold an arbitrary object + +`shared_ptr` can act as a generic object pointer similar to `void*`. When a `shared_ptr` instance constructed as: + + shared_ptr pv(new X); + +is destroyed, it will correctly dispose of the `X` object by executing `~X`. + +This propery can be used in much the same manner as a raw `void*` is used to temporarily strip type information from an object pointer. +A `shared_ptr` can later be cast back to the correct type by using `<>`. + +## Associating arbitrary data with heterogeneous `shared_ptr` instances + +`shared_ptr` and `weak_ptr` support `operator<` comparisons required by standard associative containers such as `std::map`. This can be +used to non-intrusively associate arbitrary data with objects managed by `shared_ptr`: + +``` +typedef int Data; + +std::map, Data> userData; +// or std::map, Data> userData; to not affect the lifetime + +shared_ptr px(new X); +shared_ptr pi(new int(3)); + +userData[px] = 42; +userData[pi] = 91; +``` + +## Using `shared_ptr` as a `CopyConstructible` mutex lock + +Sometimes it's necessary to return a mutex lock from a function, and a noncopyable lock cannot be returned by value. It is possible to use `shared_ptr` as a mutex lock: + +``` +class mutex +{ +public: + + void lock(); + void unlock(); +}; + +shared_ptr lock(mutex & m) +{ + m.lock(); + return shared_ptr(&m, mem_fn(&mutex::unlock)); +} +``` + +Better yet, the `shared_ptr` instance acting as a lock can be encapsulated in a dedicated `shared_lock` class: + +``` +class shared_lock +{ +private: + + shared_ptr pv; + +public: + + template explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {} +}; +``` + +`shared_lock` can now be used as: + + shared_lock lock(m); + +Note that `shared_lock` is not templated on the mutex type, thanks to `shared_ptr`’s ability to hide type information. + +## Using shared_ptr to wrap member function calls + +`shared_ptr` implements the ownership semantics required from the `Wrap/CallProxy` scheme described in Bjarne Stroustrup's article +"Wrapping C++ Member Function Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below: + +``` +template class pointer +{ +private: + + T * p_; + +public: + + explicit pointer(T * p): p_(p) + { + } + + shared_ptr operator->() const + { + p_->prefix(); + return shared_ptr(p_, mem_fn(&T::suffix)); + } +}; + +class X +{ +private: + + void prefix(); + void suffix(); + friend class pointer; + +public: + + void f(); + void g(); +}; + +int main() +{ + X x; + + pointer px(&x); + + px->f(); + px->g(); +} +``` + +## Delayed deallocation + +In some situations, a single `px.reset()` can trigger an expensive deallocation in a performance-critical region: + +``` +class X; // ~X is expensive + +class Y +{ + shared_ptr px; + +public: + + void f() + { + px.reset(); + } +}; +``` + +The solution is to postpone the potential deallocation by moving `px` to a dedicated free list that can be periodically emptied when performance and response times are not an issue: + +``` +vector< shared_ptr > free_list; + +class Y +{ + shared_ptr px; + +public: + + void f() + { + free_list.push_back(px); + px.reset(); + } +}; + +// periodically invoke free_list.clear() when convenient +``` + +Another variation is to move the free list logic to the construction point by using a delayed deleter: + +``` +struct delayed_deleter +{ + template void operator()(T * p) + { + try + { + shared_ptr pv(p); + free_list.push_back(pv); + } + catch(...) + { + } + } +}; +``` + +[#techniques_weak_without_shared] +## Weak pointers to objects not managed by a shared_ptr + +Make the object hold a `shared_ptr` to itself, using a `null_deleter`: + +``` +class X +{ +private: + + shared_ptr this_; + int i_; + +public: + + explicit X(int i): this_(this, null_deleter()), i_(i) + { + } + + // repeat in all constructors (including the copy constructor!) + + X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_) + { + } + + // do not forget to not assign this_ in the copy assignment + + X & operator=(X const & rhs) + { + i_ = rhs.i_; + } + + weak_ptr get_weak_ptr() const { return this_; } +}; +``` + +When the object's lifetime ends, `X::this_` will be destroyed, and all weak pointers will automatically expire. diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc new file mode 100644 index 0000000..d51eaa1 --- /dev/null +++ b/doc/smart_ptr/weak_ptr.adoc @@ -0,0 +1,298 @@ +//// +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2005, 2017 Peter Dimov + +Distributed under the Boost Software License, Version 1.0. + +See accompanying file LICENSE_1_0.txt or copy at +http://www.boost.org/LICENSE_1_0.txt +//// + +[#weak_ptr] +# weak_ptr: Non-owning Observer +:toc: +:toc-title: +:idprefix: weak_ptr_ + +## Description + +The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`. +To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking +`weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the +object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted +object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will +return an empty `shared_ptr`. + +Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so +can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard +library's associative containers. + +`weak_ptr` operations never throw exceptions. + +The class template is parameterized on `T`, the type of the object pointed to. + +Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is +often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined +behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent +piece of code: + +``` +shared_ptr p(new int(5)); +weak_ptr q(p); + +// some time later + +if(int * r = q.get()) +{ + // use *r +} +``` + +Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer. + +The solution to this problem is to create a temporary `shared_ptr` from `q`: + +``` +shared_ptr p(new int(5)); +weak_ptr q(p); + +// some time later + +if(shared_ptr r = q.lock()) +{ + // use *r +} +``` + +Now `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 +`r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction. + +## Synopsis + +`weak_ptr` is defined in ``. + +``` +namespace boost { + + template class weak_ptr { + public: + + typedef /*see below*/ element_type; + + weak_ptr() noexcept; + + template weak_ptr(shared_ptr const & r) noexcept; + weak_ptr(weak_ptr const & r) noexcept; + template weak_ptr(weak_ptr const & r) noexcept; + + weak_ptr(weak_ptr && r) noexcept; + + ~weak_ptr() noexcept; + + weak_ptr & operator=(weak_ptr const & r) noexcept; + weak_ptr & operator=(weak_ptr && r) noexcept; + template weak_ptr & operator=(weak_ptr const & r) noexcept; + template weak_ptr & operator=(shared_ptr const & r) noexcept; + + long use_count() const noexcept; + bool expired() const noexcept; + + shared_ptr lock() const noexcept; + + void reset() noexcept; + + void swap(weak_ptr & b) noexcept; + + template bool owner_before( weak_ptr const & r ) const noexcept; + template bool owner_before( shared_ptr const & r ) const noexcept; + }; + + template + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; + + template void swap(weak_ptr & a, weak_ptr & b) noexcept; +} +``` + +## Members + +### element_type +``` +typedef ... element_type; +``` +`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. + +### constructors +``` +weak_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs an empty `weak_ptr`. +Postconditions:: `use_count() == 0`. + +``` +template weak_ptr(shared_ptr const & r) noexcept; +``` +``` +weak_ptr(weak_ptr const & r) noexcept; +``` +``` +template weak_ptr(weak_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Effects:: 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`. +Postconditions:: `use_count() == r.use_count()`. + +``` +weak_ptr(weak_ptr && r) noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs a `weak_ptr` that has the value `r` held. +Postconditions:: `r` is empty. + +### destructor +``` +~weak_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: Destroys this `weak_ptr` but has no effect on the object its stored pointer points to. + +### assignment +``` +weak_ptr & operator=(weak_ptr const & r) noexcept; +``` +``` +weak_ptr & operator=(weak_ptr && r) noexcept; +``` +``` +template weak_ptr & operator=(weak_ptr const & r) noexcept; +``` +``` +template weak_ptr & operator=(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `weak_ptr(r).swap(*this)`. + +NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. + +### use_count +``` +long use_count() const noexcept; +``` +[none] +* {blank} ++ +Returns:: 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`. + +### expired +``` +bool expired() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `use_count() == 0`. + +### lock +``` +shared_ptr lock() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `expired()? shared_ptr(): shared_ptr(*this)`. + +### reset +``` +void reset() noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `weak_ptr().swap(*this)`. + +### swap +``` +void swap(weak_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +``` +template bool owner_before( weak_ptr const & r ) const noexcept; +``` +``` +template bool owner_before( shared_ptr const & r ) const noexcept; +``` +[none] +* {blank} ++ +Returns:: See the description of `operator<`. + +## Free Functions + +### comparison +``` +template + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: An unspecified value such that +- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; +- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances + are equivalent if and only if they share ownership or are both empty. + +NOTE: Allows `weak_ptr` objects to be used as keys in associative containers. + +### swap +``` +template void swap(weak_ptr & a, weak_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +## Frequently Asked Questions + +[qanda] +Can an object create a weak_ptr to itself in its constructor?:: + + No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no + `shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`, + it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire. ++ +The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`: ++ +``` +class X +{ +private: + + X(); + +public: + + static shared_ptr create() + { + shared_ptr px(new X); + // create weak pointers from px here + return px; + } +}; +``` diff --git a/enable_shared_from_this.html b/enable_shared_from_this.html deleted file mode 100644 index f04f312..0000000 --- a/enable_shared_from_this.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - enable_shared_from_this - - - -

boost.png (6897 bytes)enable_shared_from_this

-

Purpose

-

- The header <boost/enable_shared_from_this.hpp> defines - the class template enable_shared_from_this. It is used as a - base class that allows a shared_ptr or - a weak_ptr to the current object to be obtained - from within a member function. -

-

enable_shared_from_this<T> defines two member functions - called shared_from_this that return a shared_ptr<T> - and shared_ptr<T const>, depending on constness, to this. - It also defines two member functions called weak_from_this that return - a corresponding weak_ptr. -

-

Example

-
-#include <boost/enable_shared_from_this.hpp>
-#include <boost/shared_ptr.hpp>
-#include <cassert>
-
-class Y: public boost::enable_shared_from_this<Y>
-{
-public:
-
-    boost::shared_ptr<Y> f()
-    {
-        return shared_from_this();
-    }
-};
-
-int main()
-{
-    boost::shared_ptr<Y> p(new Y);
-    boost::shared_ptr<Y> q = p->f();
-    assert(p == q);
-    assert(!(p < q || q < p)); // p and q must share ownership
-}
-
-

Synopsis

-
-namespace boost
-{
-
-template<class T> class enable_shared_from_this
-{
-public:
-
-    shared_ptr<T> shared_from_this();
-    shared_ptr<T const> shared_from_this() const;
-
-    weak_ptr<T> weak_from_this() noexcept;
-    weak_ptr<T const> weak_from_this() const noexcept;
-}
-
-}
-
-

template<class T> shared_ptr<T> - enable_shared_from_this<T>::shared_from_this();

-

template<class T> shared_ptr<T const> - enable_shared_from_this<T>::shared_from_this() const;

-
-

- Requires: enable_shared_from_this<T> must be an - accessible base class of T. *this must be a subobject - of an instance t of type T. -

-

- Returns: If a shared_ptr instance p that owns - t exists, a shared_ptr<T> instance r that shares - ownership with p. -

-

- Postconditions: r.get() == this. -

-

- Throws: bad_weak_ptr when no shared_ptr owns *this. -

-
-

template<class T> weak_ptr<T> - enable_shared_from_this<T>::weak_from_this() noexcept;

-

template<class T> weak_ptr<T const> - enable_shared_from_this<T>::weak_from_this() const noexcept;

-
-

- Requires: enable_shared_from_this<T> must be an - accessible base class of T. *this must be a subobject - of an instance t of type T. -

-

- Returns: If a shared_ptr instance p that owns - t exists or has existed in the past, a weak_ptr<T> instance - r that shares ownership with p. Otherwise, an empty weak_ptr. -

-
-
-

- Copyright © 2002, 2003, 2015 by Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/gccspeed.gif b/gccspeed.gif deleted file mode 100644 index d78c06b..0000000 Binary files a/gccspeed.gif and /dev/null differ diff --git a/index.html b/index.html index 0551e3c..7afe664 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ - + -Smart Pointers - - + - + +

Automatic redirection failed, please go to -smart_ptr.htm. +doc/html/smart_ptr.html. +

>(std::allocator<int>(), 8); - - -
-

template<class T, class A>
shared_ptr<T> -allocate_shared(const A& a);

-
-
Returns:
-
A shared_ptr to a value-initialized object of type -E[N].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::allocate_shared<int[8]>(std::allocator<int>());
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared(const A& a, std::size_t n, -const E& v);

-
-
Returns:
-
A shared_ptr to an object of type -E[size], where each array element of type E is -initialized to v.
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::allocate_shared<double[]>(std::allocator<double>(), 8, 1.0);
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared(const A& a, const E& v);

-
-
Returns:
-
A shared_ptr to an object of type E[N], -where each array element of type E is initialized to -v.
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::allocate_shared<double[8]>(std::allocator<double>(), 1.0);
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared_noinit(const A& a, std::size_t n);

-
-
Returns:
-
A shared_ptr to a default-initialized object of type -E[size].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::allocate_shared_noinit<int[]>(std::allocator<int>(), 8);
-
-
-
-

template<class T, class A>
shared_ptr<T> -allocate_shared_noinit(const A& a);

-
-
Returns:
-
A shared_ptr to a default-initialized object of type -E[N].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::allocate_shared_noinit<int[8]>(std::allocator<int>());
-
-
-
-

template<class T>
shared_ptr<T> -make_shared(std::size_t n);

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>(), n);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_shared<int[]>(8);
-
-
-
-

template<class T>
shared_ptr<T> -make_shared();

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>());
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::make_shared<int[8]>();
-
-
-
-

template<class T>
shared_ptr<T> -make_shared(std::size_t n, const E& v);

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>(), n, v);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_shared<double[]>(8, 1.0);
-
-
-
-

template<class T>
shared_ptr<T> -make_shared(const E& v);

-
-
Returns:
-
allocate_shared<T>(std::allocator<S>(), v);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::make_shared<double[8]>(1.0);
-
-
-

template<class T>
shared_ptr<T> -make_shared_noinit(std::size_t n);

-
-
Returns:
-
allocate_shared_noinit<T>(std::allocator<S>(), n);
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_shared_noinit<int[]>(8);
-
-
-
-

template<class T>
shared_ptr<T> -make_shared_noinit();

-
-
Returns:
-
allocate_shared_noinit<T>(std::allocator<S>());
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[N].
-
Example:
-
boost::make_shared_noinit<int[8]>();
-
-
- -
-

History

-
-
Boost 1.64
-
Glen Fernandes rewrote allocate_shared and make_shared for a more -optimal and more maintainable implementation.
-
Boost 1.56
-
Glen Fernandes updated overloads of make_shared and allocate_shared -to conform to the specification in C++ standard paper -N3870, including resolving C++ standard library -defect report DR 2070.
-
Boost 1.53
-
Glen Fernandes contributed implementations of make_shared and -allocate_shared for arrays.
-
-
-
-

References

-
    -
  1. N3870, -Extending make_shared to Support Arrays, Revision 1, Peter Dimov -& Glen Fernandes, January, 2014.
  2. -
  3. DR 2070, - -allocate_shared should use allocator_traits<A>::construct, -Jonathan Wakely, July, 2011.
  4. -
-
-
-Copyright 2012-2017 Glen Fernandes. Distributed under the -Boost Software License, -Version 1.0. - - diff --git a/make_unique.html b/make_unique.html deleted file mode 100644 index fdd5fd9..0000000 --- a/make_unique.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - -make_unique - - -

make_unique

- -
-

Introduction

-

-The header file <boost/make_unique.hpp> provides overloads of -function template make_unique for convenient creation of -std::unique_ptr objects. -

-
-
-

Synopsis

-
-

Header <boost/smart_ptr/make_unique.hpp>

-namespace boost { -
-template<class T>
std::unique_ptr<T> -make_unique();
-
-
-template<class T, class... Args>
std::unique_ptr<T> -make_unique(Args&&... args);
-
-
-template<class T>
std::unique_ptr<T> -make_unique(T&& value);
-
-
-template<class T>
std::unique_ptr<T> -make_unique(std::size_t size);
-
-
-template<class T>
std::unique_ptr<T> -make_unique_noinit();
-
-
-template<class T>
std::unique_ptr<T> -make_unique_noinit(std::size_t size);
-
-} -
-
-
-

Common Requirements

-

template<class T, Args>
-std::unique_ptr<T> make_unique(args);

-
-
Effects:
-
Allocates storage for an object of type T (or -E[size] when T is E[], where -size is determined from args as specified by -the concrete overload). The storage is initialized from -args as specified by the concrete overload. If an exception -is thrown, the functions have no effect.
-
Returns:
-
A std::unique_ptr instance that stores and owns the -address of the newly allocated and constructed object.
-
Postconditions:
-
r.get() != 0, where r is the return -value.
-
Throws:
-
std::bad_alloc, or an exception thrown from the -initialization of the object.
-
Remarks:
-
-
    -
  • When an object of a scalar type T is specified to be initialized to -a value value, or to T(args...), where -args... is a list of constructor arguments, -make_unique shall perform this initialization via the -expression new T(value) or new T(args...) -respectively.
  • -
  • When an object of type T is specified to be -value-initialized, make_unique shall perform this -initialization via the expression new T().
  • -
  • When an object of type T is specified to be -default-initialized, make_unique_noinit shall perform this -initialization via the expression new T.
  • -
-
-
-
-
-

Free functions

-
-

template<class T, class... Args>
-std::unique_ptr<T> -make_unique(Args&&... args);

-
-
Returns:
-
A std::unique_ptr to an object of type T, -initialized to std::forward<Args>(args)....
-
Remarks:
-
This overload shall only participate in overload resolution when -T is not an array type.
-
Example:
-
boost::make_unique<double>(1.0);
-
-
-
-

template<class T>
std::unique_ptr<T> -make_unique(T&& value);

-
-
Returns:
-
A std::unique_ptr to an object of type T, -initialized to std::move(value).
-
Remarks:
-
This overload shall only participate in overload resolution when -T is not an array type.
-
Example:
-
boost::make_unique<point>({1.0, -1.0});
-
-
-

template<class T>
std::unique_ptr<T> -make_unique(std::size_t size);

-
-
Returns:
-
A std::unique_ptr to a value-initialized object of type -E[size].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_unique<int[]>(8);
-
-
-
-

template<class T>
std::unique_ptr<T> -make_unique_noinit();

-
-
Returns:
-
A std::unique_ptr to a default-initialized object of -type T.
-
Remarks:
-
This overload shall only participate in overload resolution when -T is not an array type.
-
Example:
-
boost::make_unique_noinit<std::tm>();
-
-
-
-

template<class T>
std::unique_ptr<T> -make_unique_noinit(std::size_t size);

-
-
Returns:
-
A std::unique_ptr to a default-initialized object of -type E[size].
-
Remarks:
-
This overload shall only participate in overload resolution when -T is of the form E[].
-
Example:
-
boost::make_unique_noinit<char[]>(64);
-
-
-
-
-

History

-
-
Boost 1.56
-
Glen Fernandes contributed implementations of make_unique for -scalars and arrays
-
-
-
-Copyright 2012-2014 Glen Fernandes. Distributed under the -Boost Software License, -Version 1.0. - - diff --git a/msvcspeed.gif b/msvcspeed.gif deleted file mode 100644 index 56295ee..0000000 Binary files a/msvcspeed.gif and /dev/null differ diff --git a/pointer_cast.html b/pointer_cast.html deleted file mode 100644 index bf63043..0000000 --- a/pointer_cast.html +++ /dev/null @@ -1,183 +0,0 @@ - - - - pointer_cast - - - -

boost.png (6897 bytes)pointer_cast

-

The pointer cast functions (boost::static_pointer_cast boost::dynamic_pointer_cast - boost::reinterpret_pointer_cast boost::const_pointer_cast) - provide a way to write generic pointer castings for raw pointers, std::shared_ptr and std::unique_ptr. The functions - are defined in boost/pointer_cast.hpp.

-

There is test/example code in pointer_cast_test.cpp.

-

Rationale

-

Boost smart pointers usually overload those functions to provide a mechanism to - emulate pointers casts. For example, boost::shared_ptr<...> implements - a static pointer cast this way:

-
-template<class T, class U>
-    shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
-
-

Pointer cast functions from boost/pointer_cast.hpp - are overloads of boost::static_pointer_cast, boost::dynamic_pointer_cast, - boost::reinterpret_pointer_cast and boost::const_pointer_cast - for raw pointers, std::shared_ptr and std::unique_ptr. This way when developing - pointer type independent classes, for example, memory managers or shared memory compatible classes, the same - code can be used for raw and smart pointers.

-

Synopsis

-
-
-namespace boost {
-
-template<class T, class U>
-inline T* static_pointer_cast(U *ptr)
-  { return static_cast<T*>(ptr); }
-
-template<class T, class U>
-inline T* dynamic_pointer_cast(U *ptr)
-  { return dynamic_cast<T*>(ptr); }
-
-template<class T, class U>
-inline T* const_pointer_cast(U *ptr)
-  { return const_cast<T*>(ptr); }
-
-template<class T, class U>
-inline T* reinterpret_pointer_cast(U *ptr)
-  { return reinterpret_cast<T*>(ptr); }
-
-template<class T, class U>
-inline std::shared_ptr<T> static_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::shared_ptr<T> dynamic_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::shared_ptr<T> const_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::shared_ptr<T> reinterpret_pointer_cast(std::shared_ptr<U> const& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> static_pointer_cast(std::unique_ptr<U>&& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> dynamic_pointer_cast(std::unique_ptr<U>&& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> const_pointer_cast(std::unique_ptr<U>&& r);
-
-template<class T, class U>
-inline std::unique_ptr<T> reinterpret_pointer_cast(std::unique_ptr<U>&& r);
-  
-} // namespace boost
-
-
-

As you can see from the above synopsis, the pointer cast functions for raw pointers are just - wrappers around standard C++ cast operators.

- -

The pointer casts for std::shared_ptr are aliases of the corresponding standard - functions with the same names and equivalent to the - functions taking boost::shared_ptr.

- -

The pointer casts for std::unique_ptr are documented below.

- -

static_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> static_pointer_cast(unique_ptr<U>&& r); // never throws
-
-

Requires: The expression static_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: unique_ptr<T>( static_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

-

Throws: nothing.

-

Notes: the seemingly equivalent expression - unique_ptr<T>(static_cast<T*>(r.get())) - will eventually result in undefined behavior, attempting to delete the same - object twice.

-
-

const_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> const_pointer_cast(unique_ptr<U>&& r); // never throws
-
-

Requires: The expression const_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: unique_ptr<T>( const_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

-

Throws: nothing.

-
-

dynamic_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> dynamic_pointer_cast(unique_ptr<U>&& r);
-
-

Requires: The expression dynamic_cast<T*>( (U*)0 ) - must be well-formed. T must have a virtual destructor.

-

Returns:

-
    -
  • - When dynamic_cast<typename unique_ptr<T>::element_type*>(r.get()) returns a nonzero value, - unique_ptr<T>(dynamic_cast<typename unique_ptr<T>::element_type*>(r.release()));
  • -
  • - Otherwise, unique_ptr<T>().
-

Throws: nothing.

-
-

reinterpret_pointer_cast

-
template<class T, class U>
-  unique_ptr<T> reinterpret_pointer_cast(unique_ptr<U>&& r); // never throws
-
-

Requires: The expression reinterpret_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: unique_ptr<T>( reinterpret_cast<typename unique_ptr<T>::element_type*>(r.release()) ).

-

Throws: nothing.

-
- -

Example

-
-
-#include <boost/pointer_cast.hpp>
-#include <boost/shared_ptr.hpp>
-
-class base
-{
-public:
-
-   virtual ~base()
-   {
-   }
-};
-
-class derived: public base
-{
-};
-
-template <class BasePtr>
-void check_if_it_is_derived(const BasePtr &ptr)
-{
-   assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
-}
-
-int main()
-{
-   // Create a raw and a shared_ptr
-
-   base *ptr = new derived;
-   boost::shared_ptr<base> sptr(new derived);
-   
-   // Check that base pointer points actually to derived class
-
-   check_if_it_is_derived(ptr);
-   check_if_it_is_derived(sptr);
-   
-   // Ok!
-   
-   delete ptr;
-   return 0;
-}
-
-

The example demonstrates how the generic pointer casts help us create pointer - independent code.

-
-

Copyright 2005 Ion Gaztañaga. Use, modification, and distribution are subject to - the Boost Software License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

- - diff --git a/pointer_to_other.html b/pointer_to_other.html deleted file mode 100644 index e9be750..0000000 --- a/pointer_to_other.html +++ /dev/null @@ -1,108 +0,0 @@ - - - - pointer_to_other - - - -

boost.png (6897 bytes)pointer_to_other

-

- The pointer to other utility provides a way, given a source pointer type, - to obtain a pointer of the same type to another pointee type. The utility is - defined in boost/pointer_to_other.hpp.

-

There is test/example code in pointer_to_other_test.cpp.

-

Contents

- -

Rationale

-

When building pointer independent classes, like memory managers, allocators, or - containers, there is often a need to define pointers generically, so that if a - template parameter represents a pointer (for example, a raw or smart pointer to - an int), we can define another pointer of the same type to another pointee (a - raw or smart pointer to a float.)

-
template <class IntPtr>
-class FloatPointerHolder
-{   
-   // Let's define a pointer to a float
-   typedef typename boost::pointer_to_other
-      <IntPtr, float>::type float_ptr_t;
-   float_ptr_t float_ptr;
-};
-

Synopsis

-
-namespace boost {
-
-template<class T, class U>
-   struct pointer_to_other;
-
-template<class T, class U, template <class> class Sp>
-   struct pointer_to_other< Sp<T>, U >
-{
-   typedef Sp<U> type;
-};
-
-template<class T, class T2, class U,
-        template <class, class> class Sp>
-   struct pointer_to_other< Sp<T, T2>, U >
-{
-   typedef Sp<U, T2> type;
-};
-
-template<class T, class T2, class T3, class U,
-        template <class, class, class> class Sp>
-struct pointer_to_other< Sp<T, T2, T3>, U >
-{
-   typedef Sp<U, T2, T3> type;
-};
-
-template<class T, class U>
-struct pointer_to_other< T*, U > 
-{
-   typedef U* type;
-};
-
-} // namespace boost
-

If these definitions are not correct for a specific smart pointer, we can define - a specialization of pointer_to_other.

-

Example

-
// Let's define a memory allocator that can
-// work with raw and smart pointers
-
-#include <boost/pointer_to_other.hpp>
-
-template <class VoidPtr>
-class memory_allocator
-{
-   // Predefine a memory_block 
-   struct block;
-
-   // Define a pointer to a memory_block from a void pointer
-   // If VoidPtr is void *, block_ptr_t is block*
-   // If VoidPtr is smart_ptr<void>, block_ptr_t is smart_ptr<block>
-   typedef typename boost::pointer_to_other      
-            <VoidPtr, block>::type block_ptr_t;
-            
-   struct block
-   {
-      std::size_t size;
-      block_ptr_t next_block;
-   };
-
-   block_ptr_t free_blocks;
-};
-

As we can see, using pointer_to_other we can create pointer independent code.

-
-

$Date$

-

Copyright 2005, 2006 Ion Gaztañaga and Peter Dimov. Use, modification, - and distribution are subject to the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or a - copy at < http://www.boost.org/LICENSE_1_0.txt>.)

- - diff --git a/scoped_array.htm b/scoped_array.htm deleted file mode 100644 index 3624e5d..0000000 --- a/scoped_array.htm +++ /dev/null @@ -1,115 +0,0 @@ - - - - scoped_array - - - -

boost.png (6897 bytes)scoped_array class template

-

The scoped_array class template stores a pointer to a dynamically - allocated array. (Dynamically allocated arrays are allocated with the C++ new[] - expression.) The array pointed to is guaranteed to be deleted, either on - destruction of the scoped_array, or via an explicit reset.

-

The scoped_array template 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_array for pointers which should not be copied.

-

Because scoped_array is so simple, in its usual implementation every - operation is as fast as a built-in array pointer and it has no more space - overhead that a built-in array pointer.

-

It cannot be used in C++ standard library containers. See - shared_array if scoped_array does not meet your needs.

-

It cannot correctly hold a pointer to a single object. See scoped_ptr - for that usage.

-

A std::vector is an alternative to a scoped_array that is a bit - heavier duty but far more flexible. A boost::array is an alternative - that does not use dynamic allocation.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
-
-  template<class T> class scoped_array : noncopyable {
-
-    public:
-      typedef T element_type;
-
-      explicit scoped_array(T * p = 0); // never throws
-      ~scoped_array(); // never throws
-
-      void reset(T * p = 0); // never throws
-
-      T & operator[](std::ptrdiff_t i) const; // never throws
-      T * get() const; // never throws
-     
-      operator unspecified-bool-type() const; // never throws
-
-      void swap(scoped_array & b); // never throws
-  };
-
-  template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
-
-}
-

Members

-

- element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit scoped_array(T * p = 0); // never throws
-

Constructs a scoped_array, storing a copy of p, which must have - been allocated via a C++ new[] expression or be 0. T is not - required be a complete type. See the smart pointer - common requirements.

-

destructor

-
~scoped_array(); // never throws
-

Deletes the array pointed to by the stored pointer. Note that delete[] on - a pointer with a value of 0 is harmless. The guarantee that this does not throw - exceptions depends on the requirement that the deleted array's objects' - destructors do not throw exceptions. See the smart pointer - common requirements.

-

reset

-
void reset(T * p = 0); // never throws
-

- Deletes the array pointed to by the stored pointer and then stores a copy of p, - which must have been allocated via a C++ new[] expression or be 0. The - guarantee that this does not throw exceptions depends on the requirement that - the deleted array's objects' destructors do not throw exceptions. See the smart - pointer common requirements.

-

subscripting

-
T & operator[](std::ptrdiff_t i) const; // never throws
-

Returns a reference to element i of the array pointed to by the stored - pointer. Behavior is undefined and almost certainly undesirable if the stored - pointer is 0, or if i is less than 0 or is greater than or equal to the - number of elements in the array.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(scoped_array & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

swap

-
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/scoped_ptr.htm b/scoped_ptr.htm deleted file mode 100644 index 1dbfbce..0000000 --- a/scoped_ptr.htm +++ /dev/null @@ -1,180 +0,0 @@ - - - - scoped_ptr - - - -

boost.png (6897 bytes)scoped_ptr class template

-

The scoped_ptr class template stores a pointer to a dynamically allocated - object. (Dynamically allocated objects are allocated with the C++ 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 example.

-

The scoped_ptr template 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 or std::auto_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 C++ Standard Library containers. - Use shared_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. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
-
-  template<class T> class scoped_ptr : noncopyable {
-
-   public:
-     typedef T element_type;
-
-     explicit scoped_ptr(T * p = 0); // never throws
-     ~scoped_ptr(); // never throws
-
-     void reset(T * p = 0); // never throws
-
-     T & operator*() const; // never throws
-     T * operator->() const; // never throws
-     T * get() const; // never throws
-     
-     operator unspecified-bool-type() const; // never throws
-
-     void swap(scoped_ptr & b); // never throws
-  };
-
-  template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
-
-}
-

Members

-

element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit scoped_ptr(T * p = 0); // never throws
-

Constructs a scoped_ptr, storing a copy of p, which must have been - allocated via a C++ new expression or be 0. T is not required be - a complete type. See the smart pointer common - requirements.

-

destructor

-
~scoped_ptr(); // never throws
-

Destroys the object pointed to by the stored pointer, if any, as if by using delete - this->get().

-

- The guarantee that this does not throw exceptions depends on the requirement - that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

reset

-
void reset(T * p = 0); // never throws
-

- Deletes the object pointed to by the stored pointer and then stores a copy of - p, which must have been allocated via a C++ new expression or be 0. The - guarantee that this does not throw exceptions depends on the requirement that - the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

indirection

-
T & operator*() const; // never throws
-

Returns a reference to the object pointed to by the stored pointer. Behavior is - undefined if the stored pointer is 0.

-
T * operator->() const; // never throws
-

Returns the stored pointer. Behavior is undefined if the stored pointer is 0.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(scoped_ptr & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

swap

-
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-

Example

-

Here's an example that uses scoped_ptr.

-
-
#include <boost/scoped_ptr.hpp>
-#include <iostream>
-
-struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
-
-class MyClass {
-    boost::scoped_ptr<int> ptr;
-  public:
-    MyClass() : ptr(new int) { *ptr = 0; }
-    int add_one() { return ++*ptr; }
-};
-
-int main()
-{
-    boost::scoped_ptr<Shoe> 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 auto_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 C++ 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<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.

-

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 scoped_ptr_example_test.cpp - sample program includes a header file, 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 scoped_ptr_example.cpp - implementation file.

-

Frequently Asked Questions

-

Q. Why doesn't scoped_ptr have a release() member?
- A. 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)

-
-

$Date

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/shared_array.htm b/shared_array.htm deleted file mode 100644 index 8fa5a7f..0000000 --- a/shared_array.htm +++ /dev/null @@ -1,183 +0,0 @@ - - - - shared_array - - - -

boost.png (6897 bytes)shared_array class template

-

The shared_array class template stores a pointer to a dynamically - allocated array. (Dynamically allocated array are allocated with the C++ new[] - expression.) The object pointed to is guaranteed to be deleted when the last shared_array - pointing to it is destroyed or reset.

-

Every shared_array meets the CopyConstructible and Assignable - requirements of the C++ Standard Library, and so can be used in standard - library containers. Comparison operators are supplied so that shared_array - works with the standard library's associative containers.

-

Normally, a shared_array cannot correctly hold a pointer to an object - that has been allocated with the non-array form of new. See - shared_ptr for that usage.

-

Because the implementation uses reference counting, cycles of shared_array - instances will not be reclaimed. For example, if main() holds a shared_array - to A, which directly or indirectly holds a shared_array back to A, - A's use count will be 2. Destruction of the original shared_array - will leave A dangling with a use count of 1.

-

A shared_ptr to a std::vector is an alternative to a shared_array - that is a bit heavier duty but far more flexible.

-

The class template is parameterized on T, the type of the object pointed - to. T must meet the smart pointer - common requirements.

-

Synopsis

-
namespace boost {
-
-  template<class T> class shared_array {
-
-    public:
-      typedef T element_type;
-
-      explicit shared_array(T * p = 0);
-      template<class D> shared_array(T * p, D d);
-      ~shared_array(); // never throws
-
-      shared_array(shared_array const & r); // never throws
-
-      shared_array & operator=(shared_array const & r); // never throws
-
-      void reset(T * p = 0);
-      template<class D> void reset(T * p, D d);
-
-      T & operator[](std::ptrdiff_t i) const; // never throws
-      T * get() const; // never throws
-
-      bool unique() const; // never throws
-      long use_count() const; // never throws
-
-      operator unspecified-bool-type() const; // never throws
-
-      void swap(shared_array<T> & b); // never throws
-  };
-
-  template<class T>
-    bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
-  template<class T>
-    bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
-  template<class T>
-    bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
-
-  template<class T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws
-
-}
-

Members

-

element_type

-
typedef T element_type;
-

Provides the type of the stored pointer.

-

constructors

-
explicit shared_array(T * p = 0);
-

Constructs a shared_array, storing a copy of p, which must be a - pointer to an array that was allocated via a C++ new[] expression or be - 0. Afterwards, the use count is 1 (even if p == 0; see - ~shared_array). The only exception which may be thrown by this - constructor is std::bad_alloc. If an exception is thrown, delete[] p - is called.

-
template<class D> shared_array(T * p, D d);
-

Constructs a shared_array, storing a copy of p and of d. - Afterwards, the use count is 1. D's copy - constructor and destructor must not throw. When the the time comes to delete - the array pointed to by p, the object d is used in the statement d(p). - Invoking the object d with parameter p in this way must not - throw. The only exception which may be thrown by this constructor is std::bad_alloc. - If an exception is thrown, d(p) is called.

-
shared_array(shared_array const & r); // never throws
-

Constructs a shared_array, as if by storing a copy of the pointer stored - in r. Afterwards, the use count for all copies - is 1 more than the initial use count.

-

destructor

-
~shared_array(); // never throws
-

Decrements the use count. Then, if the use count is 0, - deletes the array pointed to by the stored pointer. Note that delete[] on - a pointer with a value of 0 is harmless. T need not be a complete type. - The guarantee that this does not throw exceptions depends on the requirement - that the deleted object's destructor does not throw exceptions. See the smart - pointer common requirements.

-

assignment

-
shared_array & operator=(shared_array const & r); // never throws
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object.

-

reset

-
void reset(T * p = 0);
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object. The only exception which may be thrown is std::bad_alloc. - If an exception is thrown, delete[] p is called.

-
template<class D> void reset(T * p, D d);
-

Constructs a new shared_array as described above, - then replaces this shared_array with the new one, destroying the - replaced object. D's copy constructor must not throw. The only exception - which may be thrown is std::bad_alloc. If an exception is thrown, d(p) - is called.

-

indexing

-
T & operator[](std::ptrdiff_t i) const; // never throws
-

Returns a reference to element i of the array pointed to by the stored - pointer. Behavior is undefined and almost certainly undesirable if the stored - pointer is 0, or if i is less than 0 or is greater than or equal to the - number of elements in the array.

-

get

-
T * get() const; // never throws
-

Returns the stored pointer. T need not be a complete type. See the smart - pointer common requirements.

-

unique

-
bool unique() const; // never throws
-

Returns true if no other shared_array is sharing ownership of the stored - pointer, false otherwise. T need not be a complete type. See the smart - pointer common requirements.

-

use_count

-
long use_count() const; // never throws
-

Returns the number of shared_array objects sharing ownership of the - stored pointer. T need not be a complete type. See the smart pointer - common requirements.

-

Because use_count is not necessarily efficient to implement for - implementations of shared_array that do not use an explicit reference - count, it might be removed from some future version. Thus it should be used for - debugging purposes only, and not production code.

-

conversions

-
operator unspecified-bool-type () const; // never throws
-

Returns an unspecified value that, when used in boolean contexts, is equivalent - to get() != 0.

-

swap

-
void swap(shared_ptr & b); // never throws
-

Exchanges the contents of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

Free Functions

-

comparison

-
template<class T>
-  bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws
-template<class T>
-  bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws
-template<class T>
-  bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws
-

Compares the stored pointers of the two smart pointers. T need not be a - complete type. See the smart pointer common - requirements.

-

The operator< overload is provided to define an ordering so that shared_array - objects can be used in associative containers such as std::map. The - implementation uses std::less<T *> to perform the comparison. This - ensures that the comparison is handled correctly, since the standard mandates - that relational operations on pointers are unspecified (5.9 [expr.rel] - paragraph 2) but std::less<> on pointers is well-defined (20.3.3 - [lib.comparisons] paragraph 8).

-

swap

-
template<class T>
-  void swap(shared_array<T> & a, shared_array<T> & b) // never throws
-

Equivalent to a.swap(b). Matches the interface of std::swap. - Provided as an aid to generic programming.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/shared_ptr.htm b/shared_ptr.htm deleted file mode 100644 index 1cd0bc4..0000000 --- a/shared_ptr.htm +++ /dev/null @@ -1,858 +0,0 @@ - - - - shared_ptr - - - -

boost.png (6897 bytes)shared_ptr class template

-

Introduction
- Best Practices
- Synopsis
- Members
- Free Functions
- Example
- Handle/Body Idiom
- Thread Safety
- Frequently Asked Questions
- Smart Pointer Timings
- Programming Techniques

-

Introduction

-

The shared_ptr class template stores a pointer to a dynamically allocated - object, typically with a C++ new-expression. The object pointed to is - guaranteed to be deleted when the last shared_ptr pointing to it is - destroyed or reset.

-
Example:
shared_ptr<X> p1( new X );
-shared_ptr<void> p2( new int(5) );
-
- -

shared_ptr deletes the exact pointer that has been passed at construction time, - complete with its original type, regardless of the template parameter. In the second example above, - when p2 is destroyed or reset, it will call delete on the original int* - that has been passed to the constructor, even though p2 itself is of type - shared_ptr<void> and stores a pointer of type void*.

- -

Every shared_ptr meets the CopyConstructible, MoveConstructible, - CopyAssignable and MoveAssignable - requirements of the C++ Standard Library, and can be used in standard - library containers. Comparison operators are supplied so that shared_ptr - works with the standard library's associative containers.

-

Because the implementation uses reference counting, cycles of shared_ptr instances - will not be reclaimed. For example, if main() holds a shared_ptr to - A, which directly or indirectly holds a shared_ptr back to A, - A's use count will be 2. Destruction of the original shared_ptr will - leave A dangling with a use count of 1. Use weak_ptr - to "break cycles."

-

The class template is parameterized on T, the type of the object pointed - to. shared_ptr and most of its member functions place no - requirements on T; it is allowed to be an incomplete type, or - void. Member functions that do place additional requirements - (constructors, reset) are explicitly - documented below.

-

shared_ptr<T> can be implicitly converted to shared_ptr<U> - whenever T* can be implicitly converted to U*. - In particular, shared_ptr<T> is implicitly convertible - to shared_ptr<T const>, to shared_ptr<U> - where U is an accessible base of T, and to - shared_ptr<void>.

-

shared_ptr is now part of the C++11 Standard, as std::shared_ptr.

-

Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically - allocated array. This is accomplished by using an array type (T[] or T[N]) as - the template parameter. There is almost no difference between using an unsized array, T[], - and a sized array, T[N]; the latter just enables operator[] to perform a range check - on the index.

-
Example:
shared_ptr<double[1024]> p1( new double[1024] );
-shared_ptr<double[]> p2( new double[n] );
-
- -

Best Practices

-

A simple guideline that nearly eliminates the possibility of memory leaks is: - always use a named smart pointer variable to hold the result of new. - Every occurence of the new keyword in the code should have the - form:

-
shared_ptr<T> p(new Y);
-

It is, of course, acceptable to use another smart pointer in place of shared_ptr - above; having T and Y be the same type, or - passing arguments to Y's constructor is also OK.

-

If you observe this guideline, it naturally follows that you will have no - explicit delete statements; try/catch constructs will - be rare.

-

Avoid using unnamed shared_ptr temporaries to save typing; to - see why this is dangerous, consider this example:

-
void f(shared_ptr<int>, int);
-int g();
-
-void ok()
-{
-    shared_ptr<int> p( new int(2) );
-    f( p, g() );
-}
-
-void bad()
-{
-    f( shared_ptr<int>( new int(2) ), g() );
-}
-
-

The function ok follows the guideline to the letter, whereas - bad constructs the temporary shared_ptr in place, - admitting the possibility of a memory leak. Since function arguments are - evaluated in unspecified order, it is possible for new int(2) to - be evaluated first, g() second, and we may never get to the - shared_ptrconstructor if g throws an exception. - See Herb Sutter's treatment (also - here) of the issue for more information.

-

The exception safety problem described above may also be eliminated by using - the make_shared - or allocate_shared - factory functions defined in boost/make_shared.hpp. - These factory functions also provide an efficiency benefit by consolidating allocations.

-

Synopsis

-
namespace boost {
-
-  class bad_weak_ptr: public std::exception;
-
-  template<class T> class weak_ptr;
-
-  template<class T> class shared_ptr {
-
-    public:
-
-      typedef see below element_type;
-
-      shared_ptr(); // never throws
-      shared_ptr(std::nullptr_t); // never throws
-
-      template<class Y> explicit shared_ptr(Y * p);
-      template<class Y, class D> shared_ptr(Y * p, D d);
-      template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
-      template<class D> shared_ptr(std::nullptr_t p, D d);
-      template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
-
-      ~shared_ptr(); // never throws
-
-      shared_ptr(shared_ptr const & r); // never throws
-      template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
-
-      shared_ptr(shared_ptr && r); // never throws
-      template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
-
-      template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
-
-      template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p); // never throws
-
-      template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
-
-      template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
-      template<class Y> shared_ptr(std::auto_ptr<Y> && r);
-
-      template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
-
-      shared_ptr & operator=(shared_ptr const & r); // never throws
-      template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
-
-      shared_ptr & operator=(shared_ptr const && r); // never throws
-      template<class Y> shared_ptr & operator=(shared_ptr<Y> const && r); // never throws
-
-      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
-      template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
-
-      template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
-
-      shared_ptr & operator=(std::nullptr_t); // never throws
-
-      void reset(); // never throws
-
-      template<class Y> void reset(Y * p);
-      template<class Y, class D> void reset(Y * p, D d);
-      template<class Y, class D, class A> void reset(Y * p, D d, A a);
-
-      template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
-
-      T & operator*() const; // never throws; only valid when T is not an array type
-      T * operator->() const; // never throws; only valid when T is not an array type
-
-      element_type & operator[](std::ptrdiff_t i) const; // never throws; only valid when T is an array type
-
-      element_type * get() const; // never throws
-
-      bool unique() const; // never throws
-      long use_count() const; // never throws
-
-      explicit operator bool() const; // never throws
-
-      void swap(shared_ptr & b); // never throws
-      
-      template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
-      template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
-  };
-
-  template<class T, class U>
-    bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-  template<class T, class U>
-    bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-  template<class T, class U>
-    bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-  template<class T>
-    bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
-
-  template<class T>
-    bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-  template<class T>
-    bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
-
-  template<class T>
-    bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-  template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
-
-  template<class T> typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class T, class U>
-    shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws
-
-  template<class E, class T, class Y>
-    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
-
-  template<class D, class T>
-    D * get_deleter(shared_ptr<T> const & p);
-}
-

Members

-

element_type

-
typedef ... element_type;
-
-

element_type is T when T is not an array type, - and U when T is U[] or U[N].

-
-

default constructor

-
shared_ptr(); // never throws
-shared_ptr(std::nullptr_t); // never throws
-
-

Effects: Constructs an empty shared_ptr.

-

Postconditions: use_count() == 0 && get() == 0.

-

Throws: nothing.

-
-

[The nothrow guarantee is important, since reset() is specified - in terms of the default constructor; this implies that the constructor must not - allocate memory.]

-

pointer constructor

-
template<class Y> explicit shared_ptr(Y * p);
-
-

Requirements: - Y must be a complete type. - The expression delete[] p, when T is an array type, or delete p, - when T is not an array type, - must be well-formed, must not invoke undefined behavior, and must not throw exceptions. - When T is U[N], Y (*) [N] must be convertible to T*; - when T is U[], Y (*) [] must be convertible to T*; - otherwise, Y* must be convertible to T*. -

-

Effects: - When T is not an array type, constructs a shared_ptr that owns - the pointer p. - Otherwise, constructs a shared_ptr that owns - p and a deleter of an unspecified type that calls delete[] p.

-

Postconditions: use_count() == 1 && get() == p. - If T is not an array type and p is unambiguously convertible to - enable_shared_from_this<V>* - for some V, p->shared_from_this() returns a copy of - *this.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor calls - delete[] p, when T is an array type, - or delete p, when T is not an array type.

-

Notes: p must be a pointer to an object that was - allocated via a C++ new expression or be 0. The postcondition that - use count is 1 holds even if p is 0; invoking delete - on a pointer that has a value of 0 is harmless.

-
-

[This constructor is a template in order to remember the actual - pointer type passed. The destructor will call delete with the - same pointer, complete with its original type, even when T does - not have a virtual destructor, or is void.]

-

constructors taking a deleter

-
template<class Y, class D> shared_ptr(Y * p, D d);
-template<class Y, class D, class A> shared_ptr(Y * p, D d, A a);
-template<class D> shared_ptr(std::nullptr_t p, D d);
-template<class D, class A> shared_ptr(std::nullptr_t p, D d, A a);
-
-

Requirements: - D must be CopyConstructible. The copy constructor and destructor - of D must not throw. The expression d(p) must be - well-formed, must not invoke undefined behavior, and must not throw exceptions. - A must be an Allocator, as described in section 20.1.5 - (Allocator requirements) of the C++ Standard. - When T is U[N], Y (*) [N] must be convertible to T*; - when T is U[], Y (*) [] must be convertible to T*; - otherwise, Y* must be convertible to T*. -

-

Effects: Constructs a shared_ptr that owns the pointer - p and the deleter d. The constructors taking an allocator a - allocate memory using a copy of a.

-

Postconditions: use_count() == 1 && get() == p. - If T is not an array type and p is unambiguously convertible to - enable_shared_from_this<V>* - for some V, p->shared_from_this() returns a copy of - *this.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, d(p) is called.

-

Notes: When the the time comes to delete the object pointed to by p, - the stored copy of d is invoked with the stored copy of p - as an argument.

-
-

[Custom deallocators allow a factory function returning a shared_ptr - to insulate the user from its memory allocation strategy. Since the deallocator - is not part of the type, changing the allocation strategy does not break source - or binary compatibility, and does not require a client recompilation. For - example, a "no-op" deallocator is useful when returning a shared_ptr - to a statically allocated object, and other variations allow a shared_ptr - to be used as a wrapper for another smart pointer, easing interoperability.

-

The support for custom deallocators does not impose significant overhead. Other - shared_ptr features still require a deallocator to be kept.

-

The requirement that the copy constructor of D does not throw comes from - the pass by value. If the copy constructor throws, the pointer would leak.]

-

copy and converting constructors

-
shared_ptr(shared_ptr const & r); // never throws
-template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
-
-

Requires: Y* should be convertible to T*.

-

Effects: If r is empty, constructs an empty shared_ptr; - otherwise, constructs a shared_ptr that shares ownership with r.

-

Postconditions: get() == r.get() && use_count() == - r.use_count().

-

Throws: nothing.

-
-

move constructors

-
shared_ptr(shared_ptr && r); // never throws
-template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws
-
-

Requires: Y* should be convertible to T*.

-

Effects: Move-constructs a shared_ptr from r.

-

Postconditions: *this contains the old value of r. r is empty and r.get() == 0.

-

Throws: nothing.

-
-

aliasing constructor

-
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws
-
-

Effects: constructs a shared_ptr that shares ownership with - r and stores p.

-

Postconditions: get() == p && use_count() == r.use_count().

-

Throws: nothing.

-
-

aliasing move constructor

-
template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p); // never throws
-
-

- Effects: Move-constructs a shared_ptr from r, while - storing p instead. -

-

Postconditions: get() == p and use_count() equals the old count of r. r is empty and r.get() == 0.

-

Throws: nothing.

-
-

weak_ptr constructor

-
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: Constructs a shared_ptr that shares ownership with - r and stores a copy of the pointer stored in r.

-

Postconditions: use_count() == r.use_count().

-

Throws: bad_weak_ptr when r.use_count() == 0.

-

Exception safety: If an exception is thrown, the constructor has no - effect.

-
-

auto_ptr constructors

-
template<class Y> shared_ptr(std::auto_ptr<Y> & r);
-template<class Y> shared_ptr(std::auto_ptr<Y> && r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: Constructs a shared_ptr, as if by storing a copy of r.release().

-

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor has no - effect.

-
-

unique_ptr constructor

-
template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);
-
-

Requires: Y* should be convertible to T*.

-

Effects: - Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type. - Otherwise, equivalent to shared_ptr(r.release(), del), where del is a deleter - that stores the reference rd returned from r.get_deleter() and del(p) calls rd(p).

-

Postconditions: use_count() == 1.

-

Throws: std::bad_alloc, or an implementation-defined - exception when a resource other than memory could not be obtained.

-

Exception safety: If an exception is thrown, the constructor has no - effect.

-
-

destructor

-
~shared_ptr(); // never throws
-
-

Effects:

-
    -
  • - If *this is empty, or shares ownership with - another shared_ptr instance (use_count() > 1), - there are no side effects.
  • -
  • - Otherwise, if *this owns a pointer p - and a deleter d, d(p) - is called.
  • -
  • - Otherwise, *this owns a pointer p, - and delete p is called.
  • -
-

Throws: nothing.

-
-

assignment

-
shared_ptr & operator=(shared_ptr const & r); // never throws
-template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
-template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
-
-

Effects: Equivalent to shared_ptr(r).swap(*this).

-

Returns: *this.

-

Notes: The use count updates caused by the temporary object construction - and destruction are not considered observable side effects, and the - implementation is free to meet the effects (and the implied guarantees) via - different means, without creating a temporary. In particular, in the example:

-
shared_ptr<int> p(new int);
-shared_ptr<void> q(p);
-p = p;
-q = p;
-
-

both assignments may be no-ops.

-
-
shared_ptr & operator=(shared_ptr && r); // never throws
-template<class Y> shared_ptr & operator=(shared_ptr<Y> && r); // never throws
-template<class Y> shared_ptr & operator=(std::auto_ptr<Y> && r);
-template<class Y, class D> shared_ptr & operator=(std::unique_ptr<Y, D> && r);
-
-

Effects: Equivalent to shared_ptr(std::move(r)).swap(*this).

-

Returns: *this.

-
-
shared_ptr & operator=(std::nullptr_t); // never throws
-
-

Effects: Equivalent to shared_ptr().swap(*this).

-

Returns: *this.

-
-

reset

-
void reset(); // never throws
-
-

Effects: Equivalent to shared_ptr().swap(*this).

-
-
template<class Y> void reset(Y * p);
-
-

Effects: Equivalent to shared_ptr(p).swap(*this).

-
-
template<class Y, class D> void reset(Y * p, D d);
-
-

Effects: Equivalent to shared_ptr(p, d).swap(*this).

-
-
template<class Y, class D, class A> void reset(Y * p, D d, A a);
-
-

Effects: Equivalent to shared_ptr(p, d, a).swap(*this).

-
-
template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws
-
-

Effects: Equivalent to shared_ptr(r, p).swap(*this).

-
-

indirection

-
T & operator*() const; // never throws
-
-

Requirements: T should not be an array type. The stored pointer must not be 0.

-

Returns: a reference to the object pointed to by the stored pointer.

-

Throws: nothing.

-
-
T * operator->() const; // never throws
-
-

Requirements: T should not be an array type. The stored pointer must not be 0.

-

Returns: the stored pointer.

-

Throws: nothing.

-
-
element_type & operator[](std::ptrdiff_t i) const; // never throws
-
-

Requirements: T should be an array type. The stored pointer must not be 0. - i >= 0. If T is U[N], i < N.

-

Returns: get()[i].

-

Throws: nothing.

-
-

get

-
element_type * get() const; // never throws
-
-

Returns: the stored pointer.

-

Throws: nothing.

-
-

unique

-
bool unique() const; // never throws
-
-

Returns: use_count() == 1.

-

Throws: nothing.

-

Notes: unique() may be faster than use_count(). - If you are using unique() to implement copy on write, do not rely - on a specific value when the stored pointer is zero.

-
-

use_count

-
long use_count() const; // never throws
-
-

Returns: the number of shared_ptr objects, *this included, - that share ownership with *this, or 0 when *this - is empty.

-

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code.

-
-

conversions

-
explicit operator bool() const; // never throws
-
-

Returns: get() != 0.

-

Throws: nothing.

-

Notes: This conversion operator allows shared_ptr objects to be - used in boolean contexts, like if(p && p->valid()) {}.

-
-

[The conversion to bool is not merely syntactic sugar. It allows shared_ptrs - to be declared in conditions when using dynamic_pointer_cast - or weak_ptr::lock.]

-

swap

-
void swap(shared_ptr & b); // never throws
-
-

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

swap

-
template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const; // never throws
-template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const; // never throws
-
-

Effects: See the description of operator<.

-

Throws: nothing.

-
-

Free Functions

-

comparison

-
template<class T, class U>
-  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-

Returns: a.get() == b.get().

-

Throws: nothing.

-
-
template<class T, class U>
-  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-

Returns: a.get() != b.get().

-

Throws: nothing.

-
-
template<class T>
-  bool operator==(shared_ptr<T> const & p, std::nullptr_t); // never throws
-template<class T>
-  bool operator==(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-

Returns: p.get() == 0.

-

Throws: nothing.

-
-
template<class T>
-  bool operator!=(shared_ptr<T> const & p, std::nullptr_t); // never throws
-template<class T>
-  bool operator!=(std::nullptr_t, shared_ptr<T> const & p); // never throws
-
-

Returns: p.get() != 0.

-

Throws: nothing.

-
-
template<class T, class U>
-  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
-
-

Returns: an unspecified value such that

-
    -
  • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard;
  • -
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two shared_ptr instances - are equivalent if and only if they share ownership or are both empty.
-

Throws: nothing.

-

Notes: Allows shared_ptr objects to be used as keys in - associative containers.

-
-

[Operator< has been preferred over a std::less - specialization for consistency and legality reasons, as std::less - is required to return the results of operator<, and many - standard algorithms use operator< instead of std::less - for comparisons when a predicate is not supplied. Composite objects, like std::pair, - also implement their operator< in terms of their contained - subobjects' operator<.

-

The rest of the comparison operators are omitted by design.]

-

swap

-
template<class T>
-  void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

[swap is defined in the same namespace as shared_ptr - as this is currently the only legal way to supply a swap function - that has a chance to be used by the standard library.]

-

get_pointer

-
template<class T>
-  typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws
-
-

Returns: p.get().

-

Throws: nothing.

-

Notes: Provided as an aid to generic programming. Used by - mem_fn.

-
-

static_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression static_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-

Notes: the seemingly equivalent expression - shared_ptr<T>(static_cast<T*>(r.get())) - will eventually result in undefined behavior, attempting to delete the same - object twice.

-
-

const_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression const_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-
-

dynamic_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);
-
-

Requires: The expression dynamic_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns:

-
    -
  • - When dynamic_cast<typename shared_ptr<T>::element_type*>(r.get()) returns a nonzero value p, - shared_ptr<T>(r, p);
  • -
  • - Otherwise, shared_ptr<T>().
-

Throws: nothing.

-
-

reinterpret_pointer_cast

-
template<class T, class U>
-  shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws
-
-

Requires: The expression reinterpret_cast<T*>( (U*)0 ) - must be well-formed.

-

Returns: shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) ).

-

Throws: nothing.

-
-

operator<<

-
template<class E, class T, class Y>
-    std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
-
-

Effects: os << p.get();.

-

Returns: os.

-
-

get_deleter

-
template<class D, class T>
-    D * get_deleter(shared_ptr<T> const & p);
-
-

Returns: If *this owns a deleter d - of type (cv-unqualified) D, returns &d; - otherwise returns 0.

-

Throws: nothing.

-
-

Example

-

See shared_ptr_example.cpp for a - complete example program. The program builds a std::vector and std::set - of shared_ptr objects.

-

Note that after the containers have been populated, some of the shared_ptr - objects will have a use count of 1 rather than a use count of 2, since the set - is a std::set rather than a std::multiset, and thus does not - contain duplicate entries. Furthermore, the use count may be even higher at - various times while push_back and insert container operations are - performed. More complicated yet, the container operations may throw exceptions - under a variety of circumstances. Getting the memory management and exception - handling in this example right without a smart pointer would be a nightmare.

-

Handle/Body Idiom

-

One common usage of shared_ptr is to implement a handle/body (also called - pimpl) idiom which avoids exposing the body (implementation) in the header - file.

-

The shared_ptr_example2_test.cpp - sample program includes a header file, shared_ptr_example2.hpp, - which uses a shared_ptr to an incomplete type to hide the - implementation. The instantiation of member functions which require a complete - type occurs in the shared_ptr_example2.cpp - implementation file. Note that there is no need for an explicit destructor. - Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete - type.

-

Thread Safety

-

shared_ptr objects offer the same level of thread safety as - built-in types. A shared_ptr instance can be "read" (accessed - using only const operations) simultaneously by multiple threads. Different shared_ptr - instances can be "written to" (accessed using mutable operations such as operator= - or reset) simultaneously by multiple threads (even - when these instances are copies, and share the same reference count - underneath.)

-

Any other simultaneous accesses result in undefined behavior.

-

Examples:

-
shared_ptr<int> p(new int(42));
-
-//--- Example 1 ---
-
-// thread A
-shared_ptr<int> p2(p); // reads p
-
-// thread B
-shared_ptr<int> p3(p); // OK, multiple reads are safe
-
-//--- Example 2 ---
-
-// thread A
-p.reset(new int(1912)); // writes p
-
-// thread B
-p2.reset(); // OK, writes p2
-
-//--- Example 3 ---
-
-// thread A
-p = p3; // reads p3, writes p
-
-// thread B
-p3.reset(); // writes p3; undefined, simultaneous read/write
-
-//--- Example 4 ---
-
-// thread A
-p3 = p2; // reads p2, writes p3
-
-// thread B
-// p2 goes out of scope: undefined, the destructor is considered a "write access"
-
-//--- Example 5 ---
-
-// thread A
-p3.reset(new int(1));
-
-// thread B
-p3.reset(new int(2)); // undefined, multiple writes
-
-

 

-

Starting with Boost release 1.33.0, shared_ptr uses a lock-free - implementation on most common platforms.

-

If your program is single-threaded and does not link to any libraries that might - have used shared_ptr in its default configuration, you can - #define the macro BOOST_SP_DISABLE_THREADS on a - project-wide basis to switch to ordinary non-atomic reference count updates.

-

(Defining BOOST_SP_DISABLE_THREADS in some, but not all, - translation units is technically a violation of the One Definition Rule and - undefined behavior. Nevertheless, the implementation attempts to do its best to - accommodate the request to use non-atomic updates in those translation units. - No guarantees, though.)

-

You can define the macro BOOST_SP_USE_PTHREADS to turn off the - lock-free platform-specific implementation and fall back to the generic - pthread_mutex_t-based code.

-

Frequently Asked Questions

-

Q. There are several variations of shared pointers, with different - tradeoffs; why does the smart pointer library supply only a single - implementation? It would be useful to be able to experiment with each type so - as to find the most suitable for the job at hand?

-

- A. An important goal of shared_ptr is to provide a - standard shared-ownership pointer. Having a single pointer type is important - for stable library interfaces, since different shared pointers typically cannot - interoperate, i.e. a reference counted pointer (used by library A) cannot share - ownership with a linked pointer (used by library B.) -

-

Q. Why doesn't shared_ptr have template parameters supplying - traits or policies to allow extensive user customization?

-

- A. Parameterization discourages users. The shared_ptr template is - carefully crafted to meet common needs without extensive parameterization. Some - day a highly configurable smart pointer may be invented that is also very easy - to use and very hard to misuse. Until then, shared_ptr is the smart - pointer of choice for a wide range of applications. (Those interested in policy - based smart pointers should read - Modern C++ Design by Andrei Alexandrescu.) -

-

Q. I am not convinced. Default parameters can be used where appropriate - to hide the complexity. Again, why not policies?

-

- A. Template parameters affect the type. See the answer to the first - question above. -

-

Q. Why doesn't shared_ptr use a linked list implementation?

-

- A. A linked list implementation does not offer enough advantages to - offset the added cost of an extra pointer. See timings - page. In addition, it is expensive to make a linked list implementation thread - safe. -

-

Q. Why doesn't shared_ptr (or any of the other Boost smart - pointers) supply an automatic conversion to T*?

-

- A. Automatic conversion is believed to be too error prone. -

-

Q. Why does shared_ptr supply use_count()?

-

- A. As an aid to writing test cases and debugging displays. One of the - progenitors had use_count(), and it was useful in tracking down bugs in a - complex project that turned out to have cyclic-dependencies. -

-

Q. Why doesn't shared_ptr specify complexity requirements?

-

- A. Because complexity requirements limit implementors and complicate the - specification without apparent benefit to shared_ptr users. For example, - error-checking implementations might become non-conforming if they had to meet - stringent complexity requirements. -

-

Q. Why doesn't shared_ptr provide a release() function?

-

- A. shared_ptr cannot give away ownership unless it's unique() - because the other copy will still destroy the object.

-

Consider:

-
shared_ptr<int> a(new int);
-shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
-
-int * p = a.release();
-
-// Who owns p now? b will still call delete on it in its destructor.
-
-

Furthermore, the pointer returned by release() would be difficult - to deallocate reliably, as the source shared_ptr could have been created - with a custom deleter. -

-

Q. Why is operator->() const, but its return value is a - non-const pointer to the element type?

-

- A. Shallow copy pointers, including raw pointers, typically don't - propagate constness. It makes little sense for them to do so, as you can always - obtain a non-const pointer from a const one and then proceed to modify the - object through it. shared_ptr is "as close to raw pointers as possible - but no closer". -

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005, 2012, 2013 Peter Dimov. Distributed under the Boost Software License, - Version 1.0. See accompanying file LICENSE_1_0.txt - or copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/smart_ptr.htm b/smart_ptr.htm deleted file mode 100644 index 0388cc7..0000000 --- a/smart_ptr.htm +++ /dev/null @@ -1,224 +0,0 @@ - - - - Smart Pointers - - - -

boost.png (6897 bytes)Smart Pointers

-

Introduction
- Common Requirements
- Exception Safety
- Exception-specifications
- History and Acknowledgements
- References

-

Introduction

-

Smart pointers are objects which store pointers to dynamically allocated (heap) - objects. They behave much like built-in C++ pointers except that they - automatically delete the object pointed to at the appropriate time. Smart - pointers are particularly useful in the face of exceptions as they ensure - proper destruction of dynamically allocated objects. They can also be used to - keep track of dynamically allocated objects shared by multiple owners.

-

Conceptually, smart pointers are seen as owning the object pointed to, and thus - responsible for deletion of the object when it is no longer needed.

-

The smart pointer library provides six smart pointer class templates:

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
scoped_ptr<boost/scoped_ptr.hpp>Simple sole ownership of single objects. Noncopyable.
scoped_array<boost/scoped_array.hpp>Simple sole ownership of arrays. Noncopyable.
shared_ptr<boost/shared_ptr.hpp>Object ownership shared among multiple pointers.
shared_array<boost/shared_array.hpp>Array ownership shared among multiple pointers.
weak_ptr<boost/weak_ptr.hpp>Non-owning observers of an object owned by shared_ptr.
intrusive_ptr<boost/intrusive_ptr.hpp>Shared ownership of objects with an embedded reference count.
-
-

These templates are designed to complement the std::auto_ptr template.

-

They are examples of the "resource acquisition is initialization" idiom - described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition, - Section 14.4, Resource Management.

-

Additionally, the smart pointer library provides efficient factory functions - for creating smart pointer objects:

-
- - - - - - - - - - - - - - - - -
make_shared, allocate_shared for objects<boost/make_shared.hpp>Efficient creation of shared_ptr objects.
make_shared, allocate_shared for arrays<boost/make_shared.hpp>Efficient creation of shared_ptr arrays.
make_unique<boost/make_unique.hpp>Creation of unique_ptr objects and arrays.
-
-

A test program, smart_ptr_test.cpp, is - provided to verify correct operation.

-

A page on compatibility with older versions of - the Boost smart pointer library describes some of the changes since earlier - versions of the smart pointer implementation.

-

A page on smart pointer timings will be of interest - to those curious about performance issues.

-

A page on smart pointer programming techniques lists - some advanced applications of shared_ptr and weak_ptr.

-

Common Requirements

-

These smart pointer class templates have a template parameter, T, which - specifies the type of the object pointed to by the smart pointer. The behavior - of the smart pointer templates is undefined if the destructor or operator delete - for objects of type T throw exceptions.

-

T may be an incomplete type at the point of smart pointer declaration. - Unless otherwise specified, it is required that T be a complete type at - points of smart pointer instantiation. Implementations are required to diagnose - (treat as an error) all violations of this requirement, including deletion of - an incomplete type. See the description of the - checked_delete function template.

-

Note that shared_ptr does not have this restriction, as most of - its member functions do not require T to be a complete type.

-

Rationale

-

The requirements on T are carefully crafted to maximize safety yet allow - handle-body (also called pimpl) and similar idioms. In these idioms a smart - pointer may appear in translation units where T is an incomplete type. - This separates interface from implementation and hides implementation from - translation units which merely use the interface. Examples described in the - documentation for specific smart pointers illustrate use of smart pointers in - these idioms.

-

Note that scoped_ptr requires that T be a complete type at - destruction time, but shared_ptr does not.

-

Exception Safety

-

Several functions in these smart pointer classes are specified as having "no - effect" or "no effect except such-and-such" if an exception is thrown. This - means that when an exception is thrown by an object of one of these classes, - the entire program state remains the same as it was prior to the function call - which resulted in the exception being thrown. This amounts to a guarantee that - there are no detectable side effects. Other functions never throw exceptions. - The only exception ever thrown by functions which do throw (assuming T meets - the common requirements) is std::bad_alloc, - and that is thrown only by functions which are explicitly documented as - possibly throwing std::bad_alloc.

-

Exception-specifications

-

Exception-specifications are not used; see - exception-specification rationale.

-

All the smart pointer templates contain member functions which can never throw - exceptions, because they neither throw exceptions themselves nor call other - functions which may throw exceptions. These members are indicated by a comment: - // never throws. -

-

Functions which destroy objects of the pointed to type are prohibited from - throwing exceptions by the common requirements.

-

History and Acknowledgements

-

February 2017. Glen Fernandes rewrote allocate_shared - and make_shared for arrays for a more optimal and more - maintainable implementation.

-

February 2014. Glen Fernandes updated overloads of make_shared and - allocate_shared to conform to the specification in C++ standard paper - [D&F-14], and implemented make_unique for - arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and - array implementations, respectively, to resolve C++ standard library defect - 2070.

-

November 2012. Glen Fernandes provided implementations of make_shared - and allocate_shared for arrays. They achieve a single allocation for an - array that can be initialized with constructor arguments or initializer lists - as well as overloads for default initialization and no value initialization. - See the make_shared and allocate_shared for - arrays page for more information.

-

January 2002. Peter Dimov reworked all four classes, adding features, fixing - bugs, and splitting them into four separate headers, and added weak_ptr. - See the compatibility page for a summary of the - changes.

-

May 2001. Vladimir Prus suggested requiring a complete type on destruction. - Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman - Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and - others.

-

November 1999. Darin Adler provided operator ==, operator !=, and std::swap - and std::less specializations for shared types.

-

September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

-

May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a - number of suggestions resulting in numerous improvements.

-

October 1998. Beman Dawes proposed reviving the original semantics under the - names safe_ptr and counted_ptr, meeting of Per Andersson, Matt - Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar Kühl, - Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new - class names were finalized, it was decided that there was no need to exactly - follow the std::auto_ptr interface, and various function signatures and - semantics were finalized.

-

Over the next three months, several implementations were considered for shared_ptr, - and discussed on the boost.org mailing list. - The implementation questions revolved around the reference count which must be - kept, either attached to the pointed to object, or detached elsewhere. Each of - those variants have themselves two major variants: -

    -
  • - Direct detached: the shared_ptr contains a pointer to the object, and a pointer - to the count. -
  • - Indirect detached: the shared_ptr contains a pointer to a helper object, which - in turn contains a pointer to the object and the count. -
  • - Embedded attached: the count is a member of the object pointed to. -
  • - Placement attached: the count is attached via operator new manipulations.
  • -
-

Each implementation technique has advantages and disadvantages. We went so far - as to run various timings of the direct and indirect approaches, and found that - at least on Intel Pentium chips there was very little measurable difference. - Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar - Kühl suggested an elegant partial template specialization technique to allow - users to choose which implementation they preferred, and that was also - experimented with.

-

But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage - users", and in the end we choose to supply only the direct implementation.

-

Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named auto_ptr - and counted_ptr which were very similar to what we now call scoped_ptr - and shared_ptr. [Col-94] In one of the very few - cases where the Library Working Group's recommendations were not followed by - the full committee, counted_ptr was rejected and surprising - transfer-of-ownership semantics were added to auto_ptr.

-

References

-

[D&F-14] Peter Dimov & Glen Fernandes, - Extending make_shared to Support Arrays, Revision 1, C++ committee document N3870, - January, 2014.

-

[Col-94] Gregory Colvin, - Exception Safe Smart Pointers, C++ committee document 94-168/N0555, - July, 1994.

-

[E&D-94] John R. Ellis & David L. Detlefs, - Safe, Efficient Garbage Collection for C++, Usenix Proceedings, - February, 1994. This paper includes an extensive discussion of weak pointers - and an extensive bibliography.

-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Distributed under the Boost Software License, Version 1.0. See accompanying - file LICENSE_1_0.txt or copy at - http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/smarttest.zip b/smarttest.zip deleted file mode 100644 index 2464b10..0000000 Binary files a/smarttest.zip and /dev/null differ diff --git a/smarttests.htm b/smarttests.htm deleted file mode 100644 index 2551ae4..0000000 --- a/smarttests.htm +++ /dev/null @@ -1,542 +0,0 @@ - - - - - -Smart Pointer Timings - - - - - -

boost.png (6897 bytes)Smart Pointer Timings

- -

In late January 2000, Mark Borgerding put forward a suggestion to boost for - a new design of smart pointer whereby an intrusive doubly linked list is used - to join together all instances of smart pointers sharing a given raw pointer. - This allowed avoidance of the costly heap allocation of a reference count that - occurred in the initial construction of the then current version of boost::shared_ptr. - Of course, nothing is for free and the benefit here was gained at the expense - of increased size and more costly copy operations. A debate ensued on the boost - mailing list and the tests which this page describes were performed to provide - a guide for current and future investigations into smart pointer implementation - strategies.

-

Thanks are due to Dave Abrahams, -Gavin Collings, -Greg Colvin and -Beman Dawes - for test code and trial implementations, the final version of which can be found - in .zip format here.

-

Description

-

Two tests were run: the first aimed to obtain timings for two basic individual - operations:

-
    -
  1. Initial construction from raw pointer.
  2. -
  3. An amortized copy operation consisting of half an assignment and half a - copy construction - designed to reflect average usage.
  4. -
-

The second attempted to gain more insight into normal usage by timing the fill - and sort algorithms for vectors and lists filled with the various smart pointers.

-

Five smart pointer implementation strategies were tested:

-
    -
  1. Counted pointer using a heap allocated reference count, this is referred - to as simple counted.
  2. -
  3. Counted pointer using a special purpose allocator for the reference count - - special counted.
  4. -
  5. Counted pointer using an intrusive reference count - intrusive.
  6. -
  7. Linked pointer as described above - linked.
  8. -
  9. Cyclic pointer, a counted implementation using a std::deque for allocation - with provision for weak pointers and garbage collection of cycles of pointers - - cyclic.
  10. -
-

on two compilers:

-
    -
  1. MSVC 6.0 service pack 3, using default release optimization mode (/O2 - - optimized for speed, no inlining of functions defined outside a class body - unless specified as inline).
  2. -
  3. gcc 2.95.2 using full optimization (-O3 -DNDEBUG).
  4. -
-

Additionally, generated pointer sizes (taking into account struct alignment) - were compared, as were generated code sizes for MSVC mainly by manual inspection - of generated assembly code - a necessity due to function inlining.

-

All tests were run on a PII-200 running Windows NT version 4.0

-

 

-

Operation Timing Test Results

-

The following graphs show the overall time in nanoseconds to acquire a pointer - (default construction) perform n amortized copy operations on it and finally - release it. The initial allocation time for the contained pointer is not included, - although the time for it's deallocation is. The contained pointer pointed to - a trivial class, but for the inclusion of an intrusive reference count for the - benefit of the intrusive counted shared pointer. A dumb pointer (i.e. a smart - pointer that simply acquires and releases its contained pointer with no extra - overhead) and a raw pointer were also included for comparison.

- - - - - - - - - - - - - - - - - - - - - - - - - - -
   
  MSVC speed graph 
   
 GCC speed graph 
   
-

 

-

Fitting straight lines to the above plots gives the following figures for initialization - and amortized copy operation for the two compilers (times in nanoseconds, errors - at two standard deviations) : -

-

 

-

MSVC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
initialization
-
copy operation
-
simple counted
-
3000 +/- 170104 +/- 31
-
special counted
-
1330 +/- 5085 +/- 9
-
intrusive
-
1000 +/- 2071 +/- 3
linked970 +/- 60136 +/- 10
cyclic1290 +/- 70112 +/- 12
dumb1020 +/- 2010 +/- 4
-
raw
-
1038 +/- 3010 +/- 5
-

 

-

GCC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
initialization
-
copy operation
-
simple counted
-
4620 +/- 150301 +/- 28
-
special counted
-
1990 +/- 40264 +/- 7
-
intrusive
-
1590 +/- 70181 +/- 12
linked1470 +/- 140345 +/- 26
cyclic2180 +/- 100330 +/- 18
dumb1590 +/- 7074 +/- 12
-
raw
-
1430 +/- 6027 +/- 11
-

Note that the above times include a certain amount of loop overhead etc. for - each operation. An estimate of the pure smart pointer operation time 'overhead' - can be obtained by subtracting the dumb or raw figure from the smart pointer - time of interest.

-

Detail

-

The test involved iterating a loop which creates raw pointers. These were then - shared among a varying number (set size) of smart pointers. A range of set sizes - was used and then a line fitted to get a linear relation with number of initializations - and copy-operations. A spreadsheet was used for the line fit, and to produce - the performance graphs above.

-

 

-

Container Test Results

-

To gain some insight in to operation within real life programs, this test was - devised. Smart pointers were used to fill standard containers which were then - sorted.

-

In this case, the contained pointer pointed to a class which initializes a - private data member to a random value in its default constructor. This value - is used subsequently for the sort comparison test. The class also contains an - intrusive reference count for the benefit of the intrusive counted pointer.

-

All times are in seconds for 300,000 contained pointers.

-

GCC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 vectorlist
-
-
-
fill
-
sortfillsort
-
simple counted
-
46.542.4447.093.22
-
special counted
-
14.022.837.283.21
-
intrusive
-
12.151.917.993.08
linked12.462.328.143.27
cyclic22.603.191.633.18
-
raw
-
11.810.2427.510.77
-

 

-

MSVC

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 vectorlist
-
-
-
fill
-
sortfillsort
-
simple counted
-
1.832.371.864.85
-
special counted
-
1.042.351.384.58
-
intrusive
-
1.041.841.164.29
linked1.082.001.214.33
cyclic1.382.841.474.73
-
raw
-
0.670.281.241.81
-

 

-

Code Size

-

The following code sizes were determined by inspection of generated code for - MSVC only. Sizes are given in the form N / M / I where:

-
    -
  • N is the instruction count of the operation
  • -
  • M is the size of the code in bytes
  • -
  • I determines whether generated code was inlined or not I = inline, O = "outline"
  • -
-

 

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
ptr()
-
ptr(p)ptr(ptr)op=() -
~ptr()
-
-
simple counted
-
38/110/O38/110/O9/23/I22/57/I17/40/I
-
special counted
-
50/141/O50/141/O9/23/I23/64/I13/38/I
-
intrusive
-
1/2/I3/6/I3/6/I6/11/I6/11/I
-
linked
-
5/19/I5/15/I10/30/I27/59/I14/38/I
-

During the code inspection, a couple of minor points were noticed: -

-
    -
  • Function inlining was critical to performance.
  • -
  • For MSVC, at least, a "delete 0" caused execution of 11 assembly - instructions, including a function call. So in cases where performance is - at an absolute premium it can be worth inserting the extra manual test.
  • -
-

 

-

Data Size

-

The following smart pointer sizes were obtained in bytes

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
MSVC
-
-
GCC
-
-
simple counted
-
-
8
-
-
8
-
-
special counted
-
-
8
-
-
12
-
-
intrusive
-
-
4
-
-
4
-
-
linked
-
-
12
-
-
12
-
-
cyclic
-
-
8
-
-
8
-
-

 

-

Summary

-

The timing results mainly speak for themselves: clearly an intrusive pointer - outperforms all others and a simple heap based counted pointer has poor performance - relative to other implementations. The selection of an optimal non-intrusive - smart pointer implementation is more application dependent, however. Where small - numbers of copies are expected, it is likely that the linked implementation - will be favoured. Conversely, for larger numbers of copies a counted pointer - with some type of special purpose allocator looks like a win. Other factors - to bear in mind are: -

-
    -
  • Deterministic individual, as opposed to amortized, operation time. This - weighs against any implementation depending on an allocator.
  • -
  • Multithreaded synchronization. This weighs against an implementation which - spreads its information as in the case of linked pointer.
  • -
-
-

$Date$

-

© Copyright Gavin Collings 2000. Permission to copy, use, modify, sell -and distribute this document is granted provided this copyright notice appears in all -copies. This document is provided "as is" without express or implied warranty, -and with no claim as to its suitability for any purpose.

- - diff --git a/sp_techniques.html b/sp_techniques.html deleted file mode 100644 index 7e0ce8f..0000000 --- a/sp_techniques.html +++ /dev/null @@ -1,765 +0,0 @@ - - - - Smart Pointer Programming Techniques - - - -

boost.png (6897 bytes)Smart Pointer Programming Techniques

-

Using incomplete classes for implementation hiding
- The "Pimpl" idiom
- Using abstract classes for implementation hiding
- Preventing delete px.get()
- Using a shared_ptr to hold a pointer to an array
- Encapsulating allocation details, wrapping factory - functions
- Using a shared_ptr to hold a pointer to a statically - allocated object
- Using a shared_ptr to hold a pointer to a COM object
- Using a shared_ptr to hold a pointer to an object - with an embedded reference count
- Using a shared_ptr to hold another shared - ownership smart pointer
- Obtaining a shared_ptr from a raw pointer
- Obtaining a shared_ptr (weak_ptr) - to this in a constructor
- Obtaining a shared_ptr to this
- Using shared_ptr as a smart counted handle
- Using shared_ptr to execute code on block - exit
- Using shared_ptr<void> to hold an arbitrary - object
- Associating arbitrary data with heterogeneous shared_ptr - instances
- Using shared_ptr as a CopyConstructible mutex lock
- Using shared_ptr to wrap member function calls
- Delayed deallocation
- Weak pointers to objects not managed by a shared_ptr
-

-

Using incomplete classes for implementation hiding

-

A proven technique (that works in C, too) for separating interface from - implementation is to use a pointer to an incomplete class as an opaque handle:

-
class FILE;
-
-FILE * fopen(char const * name, char const * mode);
-void fread(FILE * f, void * data, size_t size);
-void fclose(FILE * f);
-
-

It is possible to express the above interface using shared_ptr, - eliminating the need to manually call fclose:

-
class FILE;
-
-shared_ptr<FILE> fopen(char const * name, char const * mode);
-void fread(shared_ptr<FILE> f, void * data, size_t size);
-
-

This technique relies on shared_ptr's ability to execute a custom - deleter, eliminating the explicit call to fclose, and on the fact - that shared_ptr<X> can be copied and destroyed when X - is incomplete.

-

The "Pimpl" idiom

-

A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom. - The incomplete class is not exposed to the user; it is hidden behind a - forwarding facade. shared_ptr can be used to implement a "Pimpl":

-
// file.hpp:
-
-class file
-{
-private:
-
-    class impl;
-    shared_ptr<impl> pimpl_;
-
-public:
-
-    file(char const * name, char const * mode);
-
-    // compiler generated members are fine and useful
-
-    void read(void * data, size_t size);
-};
-
-
// file.cpp:
-
-#include "file.hpp"
-
-class file::impl
-{
-private:
-
-    impl(impl const &);
-    impl & operator=(impl const &);
-
-    // private data
-
-public:
-
-    impl(char const * name, char const * mode) { ... }
-    ~impl() { ... }
-    void read(void * data, size_t size) { ... }
-};
-
-file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
-{
-}
-
-void file::read(void * data, size_t size)
-{
-    pimpl_->read(data, size);
-}
-
-

The key thing to note here is that the compiler-generated copy constructor, - assignment operator, and destructor all have a sensible meaning. As a result, - file is CopyConstructible and Assignable, - allowing its use in standard containers.

-

Using abstract classes for implementation hiding

-

Another widely used C++ idiom for separating inteface and implementation is to - use abstract base classes and factory functions. The abstract classes are - sometimes called "interfaces" and the pattern is known as "interface-based - programming". Again, shared_ptr can be used as the return type of - the factory functions:

-
// X.hpp:
-
-class X
-{
-public:
-
-    virtual void f() = 0;
-    virtual void g() = 0;
-
-protected:
-
-    ~X() {}
-};
-
-shared_ptr<X> createX();
-
-
-- X.cpp:
-
-class X_impl: public X
-{
-private:
-
-    X_impl(X_impl const &);
-    X_impl & operator=(X_impl const &);
-
-public:
-
-    virtual void f()
-    {
-      // ...
-    }
-
-    virtual void g()
-    {
-      // ...
-    }
-};
-
-shared_ptr<X> createX()
-{
-    shared_ptr<X> px(new X_impl);
-    return px;
-}
-
-

A key property of shared_ptr is that the allocation, construction, deallocation, - and destruction details are captured at the point of construction, inside the - factory function. Note the protected and nonvirtual destructor in the example - above. The client code cannot, and does not need to, delete a pointer to X; - the shared_ptr<X> instance returned from createX - will correctly call ~X_impl.

-

Preventing delete px.get()

-

It is often desirable to prevent client code from deleting a pointer that is - being managed by shared_ptr. The previous technique showed one - possible approach, using a protected destructor. Another alternative is to use - a private deleter:

-
class X
-{
-private:
-
-    ~X();
-
-    class deleter;
-    friend class deleter;
-
-    class deleter
-    {
-    public:
-
-        void operator()(X * p) { delete p; }
-    };
-
-public:
-
-    static shared_ptr<X> create()
-    {
-        shared_ptr<X> px(new X, X::deleter());
-        return px;
-    }
-};
-
-

Using a shared_ptr to hold a pointer to an array

-

A shared_ptr can be used to hold a pointer to an array allocated - with new[]:

-
shared_ptr<X> px(new X[1], checked_array_deleter<X>());
-
-

Note, however, that shared_array is - often preferable, if this is an option. It has an array-specific interface, - without operator* and operator->, and does not - allow pointer conversions.

-

Encapsulating allocation details, wrapping factory - functions

-

shared_ptr can be used in creating C++ wrappers over existing C - style library interfaces that return raw pointers from their factory functions - to encapsulate allocation details. As an example, consider this interface, - where CreateX might allocate X from its own private - heap, ~X may be inaccessible, or X may be incomplete:

-
X * CreateX();
-void DestroyX(X *);
-
-

The only way to reliably destroy a pointer returned by CreateX is - to call DestroyX.

-

Here is how a shared_ptr-based wrapper may look like:

-
shared_ptr<X> createX()
-{
-    shared_ptr<X> px(CreateX(), DestroyX);
-    return px;
-}
-
-

Client code that calls createX still does not need to know how the - object has been allocated, but now the destruction is automatic.

-

Using a shared_ptr to hold a pointer to a statically - allocated object

-

Sometimes it is desirable to create a shared_ptr to an already - existing object, so that the shared_ptr does not attempt to - destroy the object when there are no more references left. As an example, the - factory function:

-
shared_ptr<X> createX();
-
-

in certain situations may need to return a pointer to a statically allocated X - instance.

-

The solution is to use a custom deleter that does nothing:

-
struct null_deleter
-{
-    void operator()(void const *) const
-    {
-    }
-};
-
-static X x;
-
-shared_ptr<X> createX()
-{
-    shared_ptr<X> px(&x, null_deleter());
-    return px;
-}
-
-

The same technique works for any object known to outlive the pointer.

-

Using a shared_ptr to hold a pointer to a COM Object

-

Background: COM objects have an embedded reference count and two member - functions that manipulate it. AddRef() increments the count. Release() - decrements the count and destroys itself when the count drops to zero.

-

It is possible to hold a pointer to a COM object in a shared_ptr:

-
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
-{
-    p->AddRef();
-    shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
-    return pw;
-}
-
-

Note, however, that shared_ptr copies created from pw will - not "register" in the embedded count of the COM object; they will share the - single reference created in make_shared_from_COM. Weak pointers - created from pw will be invalidated when the last shared_ptr - is destroyed, regardless of whether the COM object itself is still alive.

-

As explained in the mem_fn documentation, - you need to #define - BOOST_MEM_FN_ENABLE_STDCALL first.

-

Using a shared_ptr to hold a pointer to an object - with an embedded reference count

-

This is a generalization of the above technique. The example assumes that the - object implements the two functions required by intrusive_ptr, - intrusive_ptr_add_ref and intrusive_ptr_release:

-
template<class T> struct intrusive_deleter
-{
-    void operator()(T * p)
-    {
-        if(p) intrusive_ptr_release(p);
-    }
-};
-
-shared_ptr<X> make_shared_from_intrusive(X * p)
-{
-    if(p) intrusive_ptr_add_ref(p);
-    shared_ptr<X> px(p, intrusive_deleter<X>());
-    return px;
-}
-
-

Using a shared_ptr to hold another shared - ownership smart pointer

-

One of the design goals of shared_ptr is to be used in library - interfaces. It is possible to encounter a situation where a library takes a shared_ptr - argument, but the object at hand is being managed by a different reference - counted or linked smart pointer.

-

It is possible to exploit shared_ptr's custom deleter feature to - wrap this existing smart pointer behind a shared_ptr facade:

-
template<class P> struct smart_pointer_deleter
-{
-private:
-
-    P p_;
-
-public:
-
-    smart_pointer_deleter(P const & p): p_(p)
-    {
-    }
-
-    void operator()(void const *)
-    {
-        p_.reset();
-    }
-    
-    P const & get() const
-    {
-        return p_;
-    }
-};
-
-shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
-{
-    shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
-    return px;
-}
-
-

One subtle point is that deleters are not allowed to throw exceptions, and the - above example as written assumes that p_.reset() doesn't throw. If - this is not the case, p_.reset() should be wrapped in a try {} - catch(...) {} block that ignores exceptions. In the (usually - unlikely) event when an exception is thrown and ignored, p_ will - be released when the lifetime of the deleter ends. This happens when all - references, including weak pointers, are destroyed or reset.

-

Another twist is that it is possible, given the above shared_ptr instance, - to recover the original smart pointer, using - get_deleter:

-
void extract_another_from_shared(shared_ptr<X> px)
-{
-    typedef smart_pointer_deleter< another_ptr<X> > deleter;
-
-    if(deleter const * pd = get_deleter<deleter>(px))
-    {
-        another_ptr<X> qx = pd->get();
-    }
-    else
-    {
-        // not one of ours
-    }
-}
-
-

Obtaining a shared_ptr from a raw pointer

-

Sometimes it is necessary to obtain a shared_ptr given a raw - pointer to an object that is already managed by another shared_ptr - instance. Example:

-
void f(X * p)
-{
-    shared_ptr<X> px(???);
-}
-
-

Inside f, we'd like to create a shared_ptr to *p.

-

In the general case, this problem has no solution. One approach is to modify f - to take a shared_ptr, if possible:

-
void f(shared_ptr<X> px);
-
-

The same transformation can be used for nonvirtual member functions, to convert - the implicit this:

-
void X::f(int m);
-
-

would become a free function with a shared_ptr first argument:

-
void f(shared_ptr<X> this_, int m);
-
-

If f cannot be changed, but X uses intrusive counting, - use make_shared_from_intrusive described - above. Or, if it's known that the shared_ptr created in f - will never outlive the object, use a null deleter.

-

Obtaining a shared_ptr (weak_ptr) - to this in a constructor

-

Some designs require objects to register themselves on construction with a - central authority. When the registration routines take a shared_ptr, this leads - to the question how could a constructor obtain a shared_ptr to this:

-
class X
-{
-public:
-
-    X()
-    {
-        shared_ptr<X> this_(???);
-    }
-};
-
-

In the general case, the problem cannot be solved. The X instance - being constructed can be an automatic variable or a static variable; it can be - created on the heap:

-
shared_ptr<X> px(new X);
-

but at construction time, px does not exist yet, and it is - impossible to create another shared_ptr instance that shares - ownership with it.

-

Depending on context, if the inner shared_ptr this_ doesn't - need to keep the object alive, use a null_deleter as explained - here and here. If X is - supposed to always live on the heap, and be managed by a shared_ptr, - use a static factory function:

-
class X
-{
-private:
-
-    X() { ... }
-
-public:
-
-    static shared_ptr<X> create()
-    {
-        shared_ptr<X> px(new X);
-        // use px as 'this_'
-        return px;
-    }
-};
-
-

Obtaining a shared_ptr to this

-

Sometimes it is needed to obtain a shared_ptr from this - in a virtual member function under the assumption that this is - already managed by a shared_ptr. The transformations - described in the previous technique cannot be applied.

-

A typical example:

-
class X
-{
-public:
-
-    virtual void f() = 0;
-
-protected:
-
-    ~X() {}
-};
-
-class Y
-{
-public:
-
-    virtual shared_ptr<X> getX() = 0;
-
-protected:
-
-    ~Y() {}
-};
-
-// --
-
-class impl: public X, public Y
-{
-public:
-
-    impl() { ... }
-
-    virtual void f() { ... }
-
-    virtual shared_ptr<X> getX()
-    {
-        shared_ptr<X> px(???);
-        return px;
-    }
-};
-
-

The solution is to keep a weak pointer to this as a member in impl:

-
class impl: public X, public Y
-{
-private:
-
-    weak_ptr<impl> weak_this;
-
-    impl(impl const &);
-    impl & operator=(impl const &);
-
-    impl() { ... }
-
-public:
-
-    static shared_ptr<impl> create()
-    {
-        shared_ptr<impl> pi(new impl);
-        pi->weak_this = pi;
-        return pi;
-    }
-
-    virtual void f() { ... }
-
-    virtual shared_ptr<X> getX()
-    {
-        shared_ptr<X> px(weak_this);
-        return px;
-    }
-};
-
-

The library now includes a helper class template - enable_shared_from_this that can be used to encapsulate the - solution:

-
class impl: public X, public Y, public enable_shared_from_this<impl>
-{
-public:
-
-    impl(impl const &);
-    impl & operator=(impl const &);
-
-public:
-
-    virtual void f() { ... }
-
-    virtual shared_ptr<X> getX()
-    {
-        return shared_from_this();
-    }
-}
-
-

Note that you no longer need to manually initialize the weak_ptr member - in enable_shared_from_this. - Constructing a shared_ptr to impl takes care of that.

-

Using shared_ptr as a smart counted handle

-

Some library interfaces use opaque handles, a variation of the - incomplete class technique described above. An example:

-
typedef void * HANDLE;
-HANDLE CreateProcess();
-void CloseHandle(HANDLE);
-
-

Instead of a raw pointer, it is possible to use shared_ptr as the - handle and get reference counting and automatic resource management for free:

-
typedef shared_ptr<void> handle;
-
-handle createProcess()
-{
-    shared_ptr<void> pv(CreateProcess(), CloseHandle);
-    return pv;
-}
-
-

Using shared_ptr to execute code on block exit

-

shared_ptr<void> can automatically execute cleanup code when - control leaves a scope.

-
    -
  • - Executing f(p), where p is a pointer:
-
    shared_ptr<void> guard(p, f);
-
-
    -
  • - Executing arbitrary code: f(x, y):
-
    shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
-
-

For a more thorough treatment, see the article "Simplify Your Exception-Safe - Code" by Andrei Alexandrescu and Petru Marginean, available online at - http://www.cuj.com/experts/1812/alexandr.htm?topic=experts.

-

Using shared_ptr<void> to hold an arbitrary - object

-

shared_ptr<void> can act as a generic object pointer similar - to void*. When a shared_ptr<void> instance - constructed as:

-
    shared_ptr<void> pv(new X);
-
-

is destroyed, it will correctly dispose of the X object by - executing ~X.

-

This propery can be used in much the same manner as a raw void* is - used to temporarily strip type information from an object pointer. A shared_ptr<void> - can later be cast back to the correct type by using - static_pointer_cast.

-

Associating arbitrary data with heterogeneous shared_ptr - instances

-

shared_ptr and weak_ptr support operator< - comparisons required by standard associative containers such as std::map. - This can be used to non-intrusively associate arbitrary data with objects - managed by shared_ptr:

-
typedef int Data;
-
-std::map< shared_ptr<void>, Data > userData;
-// or std::map< weak_ptr<void>, Data > userData; to not affect the lifetime
-
-shared_ptr<X> px(new X);
-shared_ptr<int> pi(new int(3));
-
-userData[px] = 42;
-userData[pi] = 91;
-
-

Using shared_ptr as a CopyConstructible mutex lock

-

Sometimes it's necessary to return a mutex lock from a function, and a - noncopyable lock cannot be returned by value. It is possible to use shared_ptr - as a mutex lock:

-
class mutex
-{
-public:
-
-    void lock();
-    void unlock();
-};
-
-shared_ptr<mutex> lock(mutex & m)
-{
-    m.lock();
-    return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
-}
-
-

Better yet, the shared_ptr instance acting as a lock can be - encapsulated in a dedicated shared_lock class:

-
class shared_lock
-{
-private:
-
-    shared_ptr<void> pv;
-
-public:
-
-    template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
-};
-
-

shared_lock can now be used as:

-
    shared_lock lock(m);
-
-

Note that shared_lock is not templated on the mutex type, thanks to - shared_ptr<void>'s ability to hide type information.

-

Using shared_ptr to wrap member function calls

-

shared_ptr implements the ownership semantics required from the Wrap/CallProxy - scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function - Calls" (available online at http://www.stroustrup.com/wrapper.pdf). - An implementation is given below:

-
template<class T> class pointer
-{
-private:
-
-    T * p_;
-
-public:
-
-    explicit pointer(T * p): p_(p)
-    {
-    }
-
-    shared_ptr<T> operator->() const
-    {
-        p_->prefix();
-        return shared_ptr<T>(p_, mem_fn(&T::suffix));
-    }
-};
-
-class X
-{
-private:
-
-    void prefix();
-    void suffix();
-    friend class pointer<X>;
-    
-public:
-
-    void f();
-    void g();
-};
-
-int main()
-{
-    X x;
-
-    pointer<X> px(&x);
-
-    px->f();
-    px->g();
-}
-
-

Delayed deallocation

-

In some situations, a single px.reset() can trigger an expensive - deallocation in a performance-critical region:

-
class X; // ~X is expensive
-
-class Y
-{
-    shared_ptr<X> px;
-
-public:
-
-    void f()
-    {
-        px.reset();
-    }
-};
-
-

The solution is to postpone the potential deallocation by moving px - to a dedicated free list that can be periodically emptied when performance and - response times are not an issue:

-
vector< shared_ptr<void> > free_list;
-
-class Y
-{
-    shared_ptr<X> px;
-
-public:
-
-    void f()
-    {
-        free_list.push_back(px);
-        px.reset();
-    }
-};
-
-// periodically invoke free_list.clear() when convenient
-
-

Another variation is to move the free list logic to the construction point by - using a delayed deleter:

-
struct delayed_deleter
-{
-    template<class T> void operator()(T * p)
-    {
-        try
-        {
-            shared_ptr<void> pv(p);
-            free_list.push_back(pv);
-        }
-        catch(...)
-        {
-        }
-    }
-};
-
-

Weak pointers to objects not managed by a shared_ptr

-

Make the object hold a shared_ptr to itself, using a null_deleter:

-
class X
-{
-private:
-
-    shared_ptr<X> this_;
-    int i_;
-
-public:
-
-    explicit X(int i): this_(this, null_deleter()), i_(i)
-    {
-    }
-
-    // repeat in all constructors (including the copy constructor!)
-
-    X(X const & rhs): this_(this, null_deleter()), i_(rhs.i_)
-    {
-    }
-
-    // do not forget to not assign this_ in the copy assignment
-
-    X & operator=(X const & rhs)
-    {
-        i_ = rhs.i_;
-    }
-
-    weak_ptr<X> get_weak_ptr() const { return this_; }
-};
-
-

When the object's lifetime ends, X::this_ will be destroyed, and - all weak pointers will automatically expire.

-
-

$Date$

-

Copyright © 2003 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- - diff --git a/weak_ptr.htm b/weak_ptr.htm deleted file mode 100644 index 4c256b8..0000000 --- a/weak_ptr.htm +++ /dev/null @@ -1,240 +0,0 @@ - - - - weak_ptr - - - -

boost.png (6897 bytes)weak_ptr class template

-

Introduction
- Synopsis
- Members
- Free Functions
- Frequently Asked Questions -

-

Introduction

-

The weak_ptr class template stores a "weak reference" to an object that's - already managed by a shared_ptr. To access the object, a weak_ptr - can be converted to a shared_ptr using - the shared_ptr constructor or the member function - lock. When the last shared_ptr to the object goes - away and the object is deleted, the attempt to obtain a shared_ptr - from the weak_ptr instances that refer to the deleted object will fail: - the constructor will throw an exception of type boost::bad_weak_ptr, - and weak_ptr::lock will return an empty shared_ptr.

-

Every weak_ptr meets the CopyConstructible and Assignable requirements - of the C++ Standard Library, and so can be used in standard library containers. - Comparison operators are supplied so that weak_ptr works with the - standard library's associative containers.

-

weak_ptr operations never throw exceptions.

-

The class template is parameterized on T, the type of the object pointed - to.

-

Compared to shared_ptr, weak_ptr provides a - very limited subset of operations since accessing its stored pointer is often - dangerous in multithreaded programs, and sometimes unsafe even within a single - thread (that is, it may invoke undefined behavior.) Pretend for a moment that weak_ptr - has a get member function that returns a raw pointer, and consider this - innocent piece of code:

-
shared_ptr<int> p(new int(5));
-weak_ptr<int> q(p);
-
-// some time later
-
-if(int * r = q.get())
-{
-    // use *r
-}
-
-

Imagine that after the if, but immediately before r - is used, another thread executes the statement p.reset(). Now r - is a dangling pointer.

-

The solution to this problem is to create a temporary shared_ptr - from q:

-
shared_ptr<int> p(new int(5));
-weak_ptr<int> q(p);
-
-// some time later
-
-if(shared_ptr<int> r = q.lock())
-{
-    // use *r
-}
-
-

Now 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 r goes out of scope or is reset. By obtaining - a shared_ptr to the object, we have effectively locked it - against destruction.

-

Synopsis

-
namespace boost {
-
-  template<class T> class weak_ptr {
-
-    public:
-      typedef T element_type;
-
-      weak_ptr();
-
-      template<class Y> weak_ptr(shared_ptr<Y> const & r);
-      weak_ptr(weak_ptr const & r);
-      template<class Y> weak_ptr(weak_ptr<Y> const & r);
-
-      ~weak_ptr();
-
-      weak_ptr & operator=(weak_ptr const & r);
-      template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
-      template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
-
-      long use_count() const;
-      bool expired() const;
-      shared_ptr<T> lock() const;
-
-      void reset();
-      void swap(weak_ptr<T> & b);
-  };
-
-  template<class T, class U>
-    bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
-
-  template<class T>
-    void swap(weak_ptr<T> & a, weak_ptr<T> & b);
-}
-
-

Members

-

element_type

-
typedef T element_type;
-
-

Provides the type of the template parameter T.

-
-

constructors

-
weak_ptr();
-
-

Effects: Constructs an empty weak_ptr.

-

Postconditions: use_count() == 0.

-

Throws: nothing.

-
-
template<class Y> weak_ptr(shared_ptr<Y> const & r);
-weak_ptr(weak_ptr const & r);
-template<class Y> weak_ptr(weak_ptr<Y> const & r);
-
-

Effects: 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.

-

Postconditions: use_count() == r.use_count().

-

Throws: nothing.

-
-

destructor

-
~weak_ptr();
-
-

Effects: Destroys this weak_ptr but has no effect on the object - its stored pointer points to.

-

Throws: nothing.

-
-

assignment

-
weak_ptr & operator=(weak_ptr const & r);
-template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
-template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
-
-

Effects: Equivalent to weak_ptr(r).swap(*this).

-

Throws: nothing.

-

Notes: The implementation is free to meet the effects (and the implied - guarantees) via different means, without creating a temporary.

-
-

use_count

-
long use_count() const;
-
-

Returns: 0 if *this is empty; otherwise, the - number of shared_ptr objects that share ownership with *this.

-

Throws: nothing.

-

Notes: use_count() is not necessarily efficient. Use only - for debugging and testing purposes, not for production code.

-
-

expired

-
bool expired() const;
-
-

Returns: use_count() == 0.

-

Throws: nothing.

-

Notes: expired() may be faster than use_count().

-
-

lock

-
shared_ptr<T> lock() const;
-
-

Returns: expired()? shared_ptr<T>(): shared_ptr<T>(*this).

-

Throws: nothing.

-
-

reset

-
void reset();
-
-

Effects: Equivalent to weak_ptr().swap(*this).

-
-

swap

-
void swap(weak_ptr & b);
-
-

Effects: Exchanges the contents of the two smart pointers.

-

Throws: nothing.

-
-

Free Functions

-

comparison

-
template<class T, class U>
-  bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
-
-

Returns: an unspecified value such that

-
    -
  • - operator< is a strict weak ordering as described in section 25.3 [lib.alg.sorting] - of the C++ standard; -
  • - under the equivalence relation defined by operator<, !(a - < b) && !(b < a), two weak_ptr instances - are equivalent if and only if they share ownership or are both empty.
-

Throws: nothing.

-

Notes: Allows weak_ptr objects to be used as keys in - associative containers.

-
-

swap

-
template<class T>
-  void swap(weak_ptr<T> & a, weak_ptr<T> & b)
-
-

Effects: Equivalent to a.swap(b).

-

Throws: nothing.

-

Notes: Matches the interface of std::swap. Provided as an aid to - generic programming.

-
-

Frequently Asked Questions

-

Q. Can an object create a weak_ptr to itself in its - constructor?

-

A. No. A weak_ptr can only be created from a shared_ptr, - and at object construction time no shared_ptr to the object - exists yet. Even if you could create a temporary shared_ptr to - this, it would go out of scope at the end of the constructor, and - all weak_ptr instances would instantly expire.

-

The solution is to make the constructor private, and supply a factory function - that returns a shared_ptr:
-

-
-class X
-{
-private:
-
-    X();
-
-public:
-
-    static shared_ptr<X> create()
-    {
-        shared_ptr<X> px(new X);
-        // create weak pointers from px here
-        return px;
-    }
-};
-
-
-

$Date$

-

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. - Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version - 1.0. See accompanying file LICENSE_1_0.txt or - copy at http://www.boost.org/LICENSE_1_0.txt.

- -