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/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..e85479b --- /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: Smart Pointer Library +Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes +:toc: left +:toclevels: 3 +:idprefix: +:listing-caption: Code Example +:table-caption: Illustration +: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 + +[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..5b385cb --- /dev/null +++ b/doc/smart_ptr/enable_shared_from_this.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[#enable_shared_from_this] +# enable_shared_from_this +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/history.adoc b/doc/smart_ptr/history.adoc new file mode 100644 index 0000000..ffdb9af --- /dev/null +++ b/doc/smart_ptr/history.adoc @@ -0,0 +1,89 @@ +//// +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 +//// + +[appendix,#history] +# History and Acknowledgments +:idprefix: + +## 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`. + +## 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. + +## February 2014 + +Glen Fernandes updated overloads of `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..dec424e --- /dev/null +++ b/doc/smart_ptr/introduction.adoc @@ -0,0 +1,49 @@ +//// +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 +:toc: +:toc-title: +:idprefix: + +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: + +* `scoped_ptr`, used to contain ownership of a dynamically allocated object to the current scope; +* `scoped_array`, which provides scoped ownership for a dynamically allocated array; +* `shared_ptr`, a versatile tool for managing shared ownership of an object or array; +* `weak_ptr`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr; +* `intrusive_ptr`, a pointer to objects with an embedded reference count. + +`shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration. + +In addition, the library contains the following supporting utility functions and classes: + +* `make_shared`, a factory function for creating objects that returns a `shared_ptr`; +* `make_unique`, a factory function returning `std::unique_ptr`; +* `enable_shared_from_this`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`; +* `pointer_to_other`, a helper trait for converting one smart pointer type to another; +* `static_pointer_cast` and companions, generic smart pointer casts; +* `intrusive_ref_counter`, a helper base class containing a reference count. + +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..6bf4843 --- /dev/null +++ b/doc/smart_ptr/intrusive_ptr.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[#intrusive_ptr] +# intrusive_ptr +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/intrusive_ref_counter.adoc b/doc/smart_ptr/intrusive_ref_counter.adoc new file mode 100644 index 0000000..4a9885a --- /dev/null +++ b/doc/smart_ptr/intrusive_ref_counter.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[#intrusive_ref_counter] +# intrusive_ref_counter +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/make_shared.adoc b/doc/smart_ptr/make_shared.adoc new file mode 100644 index 0000000..2531cfe --- /dev/null +++ b/doc/smart_ptr/make_shared.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[#make_shared] +# make_shared +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/make_unique.adoc b/doc/smart_ptr/make_unique.adoc new file mode 100644 index 0000000..9cfec90 --- /dev/null +++ b/doc/smart_ptr/make_unique.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[#make_unique] +# make_unique +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/pointer_cast.adoc b/doc/smart_ptr/pointer_cast.adoc new file mode 100644 index 0000000..3041eeb --- /dev/null +++ b/doc/smart_ptr/pointer_cast.adoc @@ -0,0 +1,15 @@ +//// +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: + diff --git a/doc/smart_ptr/pointer_to_other.adoc b/doc/smart_ptr/pointer_to_other.adoc new file mode 100644 index 0000000..4c4f74d --- /dev/null +++ b/doc/smart_ptr/pointer_to_other.adoc @@ -0,0 +1,15 @@ +//// +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_to_other] +# pointer_to_other +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/scoped_array.adoc b/doc/smart_ptr/scoped_array.adoc new file mode 100644 index 0000000..9374caa --- /dev/null +++ b/doc/smart_ptr/scoped_array.adoc @@ -0,0 +1,15 @@ +//// +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_array] +# scoped_array +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/scoped_ptr.adoc b/doc/smart_ptr/scoped_ptr.adoc new file mode 100644 index 0000000..ba71827 --- /dev/null +++ b/doc/smart_ptr/scoped_ptr.adoc @@ -0,0 +1,15 @@ +//// +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 +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/shared_array.adoc b/doc/smart_ptr/shared_array.adoc new file mode 100644 index 0000000..564747f --- /dev/null +++ b/doc/smart_ptr/shared_array.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[appendix,#shared_array] +# shared_array (deprecated) +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc new file mode 100644 index 0000000..50e38a0 --- /dev/null +++ b/doc/smart_ptr/shared_ptr.adoc @@ -0,0 +1,15 @@ +//// +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_ptr] +# shared_ptr +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/techniques.adoc b/doc/smart_ptr/techniques.adoc new file mode 100644 index 0000000..13a9b18 --- /dev/null +++ b/doc/smart_ptr/techniques.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[appendix,#techniques] +# Smart Pointer Programming Techniques +:toc: +:toc-title: +:idprefix: + diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc new file mode 100644 index 0000000..ceb28cf --- /dev/null +++ b/doc/smart_ptr/weak_ptr.adoc @@ -0,0 +1,15 @@ +//// +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 +//// + +[#weak_ptr] +# weak_ptr +:toc: +:toc-title: +:idprefix: + 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: -

-

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:

- -

 

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

- -

 

-

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

- -
-

$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.

- -
    shared_ptr<void> guard(p, f);
-
- -
    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.

- -