mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-06-25 03:51:34 +02:00
Start rewriting documentation in asciidoc
This commit is contained in:
@ -1,88 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Smart Pointer Changes</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">Smart Pointer Changes</h1>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<h2>Features Requiring Code Changes to Take Advantage</h2>
|
||||
<ul>
|
||||
<li>
|
||||
The smart pointer class templates now each have their own header file. For
|
||||
compatibility, the <a href="../../boost/smart_ptr.hpp"><boost/smart_ptr.hpp></a>
|
||||
header now includes the headers for the four classic smart pointer class
|
||||
templates.
|
||||
<li>
|
||||
The <b>weak_ptr</b>
|
||||
template was added.
|
||||
<li>
|
||||
The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that
|
||||
the pointed-to object's destructor must be visible when instantiating the <b>shared_ptr</b>
|
||||
destructor. This makes it easier to have shared_ptr members in classes without
|
||||
explicit destructors.
|
||||
<li>
|
||||
A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.
|
||||
<li>
|
||||
<b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are
|
||||
provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b>
|
||||
and <b>dynamic_cast</b>
|
||||
do for pointers.
|
||||
<li>
|
||||
The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,
|
||||
although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.
|
||||
Calling <b>reset</b> with a pointer to the object that's already owned by the <b>shared_ptr</b>
|
||||
results in undefined behavior (an assertion, or eventually a double-delete if
|
||||
assertions are off).
|
||||
<li>
|
||||
The <b>BOOST_SMART_PTR_CONVERSION</b>
|
||||
feature has been removed.
|
||||
<li>
|
||||
<b>shared_ptr<void></b> is now allowed.</li>
|
||||
</ul>
|
||||
<h2>Features That Improve Robustness</h2>
|
||||
<ul>
|
||||
<li>
|
||||
The manipulation of use counts is now <a name="threadsafe">thread safe</a> on
|
||||
Windows, Linux, and platforms that support pthreads. See the <a href="../../boost/detail/atomic_count.hpp">
|
||||
<boost/detail/atomic_count.hpp></a>
|
||||
file for details
|
||||
<li>
|
||||
The new shared_ptr will always delete the object using the pointer it was
|
||||
originally constructed with. This prevents subtle problems that could happen if
|
||||
the last <b>shared_ptr</b> was a pointer to a sub-object of a class that did
|
||||
not have a virtual destructor.</li>
|
||||
</ul>
|
||||
<h2>Implementation Details</h2>
|
||||
<ul>
|
||||
<li>
|
||||
Some bugs in the assignment operator implementations and in <b>reset</b>
|
||||
have been fixed by using the "copy and swap" idiom.
|
||||
<li>
|
||||
Assertions have been added to check preconditions of various functions;
|
||||
however, since these use the new <a href="../../boost/assert.hpp"><boost/assert.hpp></a>
|
||||
header, the assertions are disabled by default.
|
||||
<li>
|
||||
The partial specialization of <b>std::less</b> has been replaced by <b>operator<</b>
|
||||
overloads which accomplish the same thing without relying on undefined
|
||||
behavior.
|
||||
<li>
|
||||
The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>,
|
||||
which has many of the same advantages for generic programming but does not
|
||||
violate the C++ standard.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
26
doc/Jamfile
Normal file
26
doc/Jamfile
Normal file
@ -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 : <location>html ;
|
||||
|
||||
pdf smart_ptr.pdf : smart_ptr.adoc ;
|
||||
explicit smart_ptr.pdf ;
|
||||
|
||||
install pdf_ : smart_ptr.pdf : <location>pdf ;
|
||||
explicit pdf_ ;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : html_ ;
|
||||
explicit boostrelease ;
|
50
doc/asciidoctor.jam
Normal file
50
doc/asciidoctor.jam
Normal file
@ -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)
|
||||
}
|
33
doc/smart_ptr-docinfo-footer.html
Normal file
33
doc/smart_ptr-docinfo-footer.html
Normal file
@ -0,0 +1,33 @@
|
||||
<style>
|
||||
|
||||
*:not(pre)>code { background: none; color: #600000; }
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
var header = document.getElementById( 'boost-common-heading-doc' );
|
||||
|
||||
if( header )
|
||||
{
|
||||
header.style.position = 'fixed';
|
||||
header.style.zIndex = '100';
|
||||
|
||||
var notice = document.getElementsByClassName( 'boost-common-header-notice' )[ 0 ];
|
||||
|
||||
if( notice )
|
||||
{
|
||||
notice.style.position = 'fixed';
|
||||
notice.style.zIndex = '101';
|
||||
}
|
||||
|
||||
var toc = document.getElementById( 'toc' );
|
||||
|
||||
if( toc )
|
||||
{
|
||||
toc.style.top = '101px';
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
70
doc/smart_ptr.adoc
Normal file
70
doc/smart_ptr.adoc
Normal file
@ -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].
|
15
doc/smart_ptr/enable_shared_from_this.adoc
Normal file
15
doc/smart_ptr/enable_shared_from_this.adoc
Normal file
@ -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:
|
||||
|
89
doc/smart_ptr/history.adoc
Normal file
89
doc/smart_ptr/history.adoc
Normal file
@ -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.
|
||||
|
49
doc/smart_ptr/introduction.adoc
Normal file
49
doc/smart_ptr/introduction.adoc
Normal file
@ -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.
|
15
doc/smart_ptr/intrusive_ptr.adoc
Normal file
15
doc/smart_ptr/intrusive_ptr.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/intrusive_ref_counter.adoc
Normal file
15
doc/smart_ptr/intrusive_ref_counter.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/make_shared.adoc
Normal file
15
doc/smart_ptr/make_shared.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/make_unique.adoc
Normal file
15
doc/smart_ptr/make_unique.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/pointer_cast.adoc
Normal file
15
doc/smart_ptr/pointer_cast.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/pointer_to_other.adoc
Normal file
15
doc/smart_ptr/pointer_to_other.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/scoped_array.adoc
Normal file
15
doc/smart_ptr/scoped_array.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/scoped_ptr.adoc
Normal file
15
doc/smart_ptr/scoped_ptr.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/shared_array.adoc
Normal file
15
doc/smart_ptr/shared_array.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/shared_ptr.adoc
Normal file
15
doc/smart_ptr/shared_ptr.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/techniques.adoc
Normal file
15
doc/smart_ptr/techniques.adoc
Normal file
@ -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:
|
||||
|
15
doc/smart_ptr/weak_ptr.adoc
Normal file
15
doc/smart_ptr/weak_ptr.adoc
Normal file
@ -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:
|
||||
|
@ -1,110 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>enable_shared_from_this</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0" />enable_shared_from_this</h1>
|
||||
<h2><a name="Purpose">Purpose</a></h2>
|
||||
<p>
|
||||
The header <code><boost/enable_shared_from_this.hpp></code> defines
|
||||
the class template <code>enable_shared_from_this</code>. It is used as a
|
||||
base class that allows a <a href="shared_ptr.htm">shared_ptr</a> or
|
||||
a <a href="weak_ptr.htm">weak_ptr</a> to the current object to be obtained
|
||||
from within a member function.
|
||||
</p>
|
||||
<p><code>enable_shared_from_this<T></code> defines two member functions
|
||||
called <code>shared_from_this</code> that return a <code>shared_ptr<T></code>
|
||||
and <code>shared_ptr<T const></code>, depending on constness, to <code>this</code>.
|
||||
It also defines two member functions called <code>weak_from_this</code> that return
|
||||
a corresponding <code>weak_ptr</code>.
|
||||
</p>
|
||||
<h2><a name="Example">Example</a></h2>
|
||||
<pre>
|
||||
#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
|
||||
}
|
||||
</pre>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
</pre>
|
||||
<h4><code>template<class T> shared_ptr<T>
|
||||
enable_shared_from_this<T>::shared_from_this();</code></h4>
|
||||
<h4><code>template<class T> shared_ptr<T const>
|
||||
enable_shared_from_this<T>::shared_from_this() const;</code></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <code>enable_shared_from_this<T></code> must be an
|
||||
accessible base class of <code>T</code>. <code>*this</code> must be a subobject
|
||||
of an instance <code>t</code> of type <code>T</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Returns:</b> If a <code>shared_ptr</code> instance <code>p</code> that <em>owns</em>
|
||||
<code>t</code> exists, a <code>shared_ptr<T></code> instance <code>r</code> that shares
|
||||
ownership with <code>p</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Postconditions:</b> <code>r.get() == this</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Throws:</b> <code>bad_weak_ptr</code> when no <code>shared_ptr</code> <em>owns</em> <code>*this</code>.
|
||||
</p>
|
||||
</blockquote>
|
||||
<h4><code>template<class T> weak_ptr<T>
|
||||
enable_shared_from_this<T>::weak_from_this() noexcept;</code></h4>
|
||||
<h4><code>template<class T> weak_ptr<T const>
|
||||
enable_shared_from_this<T>::weak_from_this() const noexcept;</code></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <code>enable_shared_from_this<T></code> must be an
|
||||
accessible base class of <code>T</code>. <code>*this</code> must be a subobject
|
||||
of an instance <code>t</code> of type <code>T</code>.
|
||||
</p>
|
||||
<p>
|
||||
<b>Returns:</b> If a <code>shared_ptr</code> instance <code>p</code> that <em>owns</em>
|
||||
<code>t</code> exists or has existed in the past, a <code>weak_ptr<T></code> instance
|
||||
<code>r</code> that shares ownership with <code>p</code>. Otherwise, an empty <code>weak_ptr</code>.
|
||||
</p>
|
||||
</blockquote>
|
||||
<hr />
|
||||
<p>
|
||||
<small>Copyright © 2002, 2003, 2015 by Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>.</small></p>
|
||||
</body>
|
||||
</html>
|
BIN
gccspeed.gif
BIN
gccspeed.gif
Binary file not shown.
Before Width: | Height: | Size: 6.4 KiB |
12
index.html
12
index.html
@ -1,13 +1,13 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Smart Pointers</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta http-equiv="refresh" content="0; URL=smart_ptr.htm">
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/smart_ptr.html">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<body>
|
||||
<p>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="smart_ptr.htm">smart_ptr.htm</a>.
|
||||
<a href="doc/html/smart_ptr.html">doc/html/smart_ptr.html</a>.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
|
@ -1,320 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>intrusive_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">intrusive_ptr class template</h1>
|
||||
<p>
|
||||
<a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#functions">Free Functions</a><br>
|
||||
</p>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>The <code>intrusive_ptr</code> class template stores a pointer to an object with an
|
||||
embedded reference count. Every new <code>intrusive_ptr</code> instance increments
|
||||
the reference count by using an unqualified call to the function <code>intrusive_ptr_add_ref</code>,
|
||||
passing it the pointer as an argument. Similarly, when an <code>intrusive_ptr</code>
|
||||
is destroyed, it calls <code>intrusive_ptr_release</code>; this function is
|
||||
responsible for destroying the object when its reference count drops to zero.
|
||||
The user is expected to provide suitable definitions of these two functions. On
|
||||
compilers that support argument-dependent lookup, <code>intrusive_ptr_add_ref</code>
|
||||
and <code>intrusive_ptr_release</code> should be defined in the namespace
|
||||
that corresponds to their parameter; otherwise, the definitions need to go in
|
||||
namespace <code>boost</code>. The library provides a helper base class template
|
||||
<code><a href="intrusive_ref_counter.html">intrusive_ref_counter</a></code> which may
|
||||
help adding support for <code>intrusive_ptr</code> to user types.</p>
|
||||
<p>The class template is parameterized on <code>T</code>, the type of the object pointed
|
||||
to. <code>intrusive_ptr<T></code> can be implicitly converted to <code>intrusive_ptr<U></code>
|
||||
whenever <code>T*</code> can be implicitly converted to <code>U*</code>.</p>
|
||||
<p>The main reasons to use <code>intrusive_ptr</code> are:</p>
|
||||
<ul>
|
||||
<li>
|
||||
Some existing frameworks or OSes provide objects with embedded reference
|
||||
counts;</li>
|
||||
<li>
|
||||
The memory footprint of <code>intrusive_ptr</code>
|
||||
is the same as the corresponding raw pointer;</li>
|
||||
<li>
|
||||
<code>intrusive_ptr<T></code> can be constructed from an arbitrary
|
||||
raw pointer of type <code>T *</code>.</li></ul>
|
||||
<p>As a general rule, if it isn't obvious whether <code>intrusive_ptr</code> better
|
||||
fits your needs than <code>shared_ptr</code>, try a <code>shared_ptr</code>-based
|
||||
design first.</p>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
template<class T> class intrusive_ptr {
|
||||
|
||||
public:
|
||||
|
||||
typedef T <a href="#element_type" >element_type</a>;
|
||||
|
||||
<a href="#constructors" >intrusive_ptr</a>(); // never throws
|
||||
<a href="#constructors" >intrusive_ptr</a>(T * p, bool add_ref = true);
|
||||
|
||||
<a href="#constructors" >intrusive_ptr</a>(intrusive_ptr const & r);
|
||||
template<class Y> <a href="#constructors" >intrusive_ptr</a>(intrusive_ptr<Y> const & r);
|
||||
|
||||
<a href="#destructor" >~intrusive_ptr</a>();
|
||||
|
||||
intrusive_ptr & <a href="#assignment" >operator=</a>(intrusive_ptr const & r);
|
||||
template<class Y> intrusive_ptr & <a href="#assignment" >operator=</a>(intrusive_ptr<Y> const & r);
|
||||
intrusive_ptr & <a href="#assignment" >operator=</a>(T * r);
|
||||
|
||||
void <a href="#reset" >reset</a>();
|
||||
void <a href="#reset" >reset</a>(T * r);
|
||||
void <a href="#reset" >reset</a>(T * r, bool add_ref);
|
||||
|
||||
T & <a href="#indirection" >operator*</a>() const; // never throws
|
||||
T * <a href="#indirection" >operator-></a>() const; // never throws
|
||||
T * <a href="#get" >get</a>() const; // never throws
|
||||
T * <a href="#detach" >detach</a>(); // never throws
|
||||
|
||||
operator <a href="#conversions" ><i>unspecified-bool-type</i></a>() const; // never throws
|
||||
|
||||
void <a href="#swap" >swap</a>(intrusive_ptr & b); // never throws
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool <a href="#comparison" >operator==</a>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
bool <a href="#comparison" >operator!=</a>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator==</a>(intrusive_ptr<T> const & a, T * b); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator!=</a>(intrusive_ptr<T> const & a, T * b); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator==</a>(T * a, intrusive_ptr<T> const & b); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator!=</a>(T * a, intrusive_ptr<T> const & b); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
bool <a href="#comparison" >operator<</a>(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws
|
||||
|
||||
template<class T> void <a href="#free-swap" >swap</a>(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws
|
||||
|
||||
template<class T> T * <a href="#get_pointer" >get_pointer</a>(intrusive_ptr<T> const & p); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> <a href="#static_pointer_cast" >static_pointer_cast</a>(intrusive_ptr<U> const & r); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> <a href="#const_pointer_cast" >const_pointer_cast</a>(intrusive_ptr<U> const & r); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
intrusive_ptr<T> <a href="#dynamic_pointer_cast" >dynamic_pointer_cast</a>(intrusive_ptr<U> const & r); // never throws
|
||||
|
||||
template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> & <a href="#insertion-operator" >operator<<</a> (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);
|
||||
|
||||
}</pre>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<blockquote>
|
||||
<p>Provides the type of the template parameter <code>T</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>intrusive_ptr(); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Postconditions:</b> <code>get() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>intrusive_ptr(T * p, bool add_ref = true);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> <code>if(p != 0 && add_ref) intrusive_ptr_add_ref(p);</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>get() == p</code>.</p>
|
||||
</blockquote>
|
||||
<pre>intrusive_ptr(intrusive_ptr const & r);
|
||||
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> <code>if(r.get() != 0) intrusive_ptr_add_ref(r.get());</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>get() == r.get()</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~intrusive_ptr();</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> <code>if(get() != 0) intrusive_ptr_release(get());</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="assignment">assignment</a></h3>
|
||||
<pre>intrusive_ptr & operator=(intrusive_ptr const & r);
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
||||
intrusive_ptr & operator=(T * r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</p>
|
||||
<p><b>Returns:</b> <code>*this</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset();</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>intrusive_ptr().swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>void reset(T * r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>void reset(T * r, bool add_ref);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>intrusive_ptr(r, add_ref).swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
|
||||
<p><b>Returns:</b> <code>*get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
|
||||
<p><b>Returns:</b> <code>get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="detach">detach</a></h3>
|
||||
<pre>T * detach(); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Postconditions:</b> <code>get() == 0</code>.</p>
|
||||
<p><b>Notes:</b> The returned pointer has an elevated reference count. This
|
||||
allows conversion of an <code>intrusive_ptr</code> back to a raw pointer,
|
||||
without the performance overhead of acquiring and dropping an extra
|
||||
reference. It can be viewed as the complement of the
|
||||
non-reference-incrementing constructor.</p>
|
||||
<p><b>Caution:</b> Using <code>detach</code> escapes the safety of automatic
|
||||
reference counting provided by <code>intrusive_ptr</code>. It should
|
||||
by used only where strictly necessary (such as when interfacing to an
|
||||
existing API), and when the implications are thoroughly understood.</p>
|
||||
</blockquote>
|
||||
<h3><a name="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
|
||||
equivalent to <code>get() != 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> This conversion operator allows <code>intrusive_ptr</code> objects to be
|
||||
used in boolean contexts, like <code>if (p && p->valid()) {}</code>.
|
||||
The actual target type is typically a pointer to a member function, avoiding
|
||||
many of the implicit conversion pitfalls.</p>
|
||||
</blockquote>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(intrusive_ptr & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<class T, class U>
|
||||
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator==(intrusive_ptr<T> const & a, U * b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() == b</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator!=(intrusive_ptr<T> const & a, U * b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() != b</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator==(T * a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a == b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator!=(T * a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a != b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>std::less<T *>()(a.get(), b.get())</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> Allows <code>intrusive_ptr</code> objects to be used as keys
|
||||
in associative containers.</p>
|
||||
</blockquote>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<class T>
|
||||
void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>a.swap(b)</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> Matches the interface of <code>std::swap</code>. Provided as an aid to
|
||||
generic programming.</p>
|
||||
</blockquote>
|
||||
<h3><a name="get_pointer">get_pointer</a></h3>
|
||||
<pre>template<class T>
|
||||
T * get_pointer(intrusive_ptr<T> const & p); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>p.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> Provided as an aid to generic programming. Used by <a href="../bind/mem_fn.html">
|
||||
mem_fn</a>.</p>
|
||||
</blockquote>
|
||||
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
|
||||
<pre>template<class T, class U>
|
||||
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>intrusive_ptr<T>(static_cast<T*>(r.get()))</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
|
||||
<pre>template<class T, class U>
|
||||
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>intrusive_ptr<T>(const_cast<T*>(r.get()))</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
|
||||
<pre>template<class T, class U>
|
||||
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>intrusive_ptr<T>(dynamic_cast<T*>(r.get()))</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="insertion-operator">operator<<</a></h3>
|
||||
<pre>template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> <code>os << p.get();</code>.</p>
|
||||
<p><b>Returns:</b> <code>os</code>.</p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p>
|
||||
<small>Copyright © 2003-2005, 2013 Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
|
||||
copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>.</small></p>
|
||||
</body>
|
||||
</html>
|
@ -1,94 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>intrusive_ref_counter</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">basic_intrusive_ref_counter class template</h1>
|
||||
<p>
|
||||
<A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Members">Members</A><br>
|
||||
</p>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>The <STRONG>intrusive_ref_counter</STRONG> class template implements a reference counter for a derived
|
||||
user's class that is intended to be used with <STRONG><a href="intrusive_ptr.html">intrusive_ptr</a></STRONG>.
|
||||
The base class has associated <STRONG>intrusive_ptr_add_ref</STRONG> and <STRONG>intrusive_ptr_release</STRONG> functions
|
||||
which modify the reference counter as needed and destroy the user's object when the counter drops to zero.</p>
|
||||
<p>The class template is parameterized on <STRONG>DerivedT</STRONG> and <STRONG>CounterPolicyT</STRONG> parameters.
|
||||
The first parameter is the user's class that derives from <STRONG>intrusive_ref_counter</STRONG>. This type
|
||||
is needed in order to destroy the object correctly when there are no references to it left.</p>
|
||||
<p>The second parameter is a policy that defines the nature of the reference counter.
|
||||
Boost.SmartPtr provides two such policies: <STRONG>thread_unsafe_counter</STRONG> and <STRONG>thread_safe_counter</STRONG>. The former
|
||||
instructs the <STRONG>intrusive_ref_counter</STRONG> base class to use a counter only suitable for a single-threaded use.
|
||||
Pointers to a single object that uses this kind of reference counter must not be used in different threads. The latter policy
|
||||
makes the reference counter thread-safe, unless the target platform doesn't support threading. Since in modern systems support for
|
||||
threading is common, the default counter policy is <STRONG>thread_safe_counter</STRONG>.</p>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
struct thread_unsafe_counter;
|
||||
struct thread_safe_counter;
|
||||
|
||||
template<class DerivedT, class CounterPolicyT = thread_safe_counter>
|
||||
class intrusive_ref_counter
|
||||
{
|
||||
public:
|
||||
<A href="#constructors" >intrusive_ref_counter</A>() = noexcept;
|
||||
<A href="#constructors" >intrusive_ref_counter</A>(intrusive_ref_counter const & r) = noexcept;
|
||||
|
||||
intrusive_ref_counter & <A href="#assignment" >operator=</A>(intrusive_ref_counter const & r) noexcept;
|
||||
|
||||
unsigned int <a href="#use_count" >use_count</a>() const noexcept;
|
||||
|
||||
protected:
|
||||
<A href="#destructor" >~intrusive_ref_counter</A>() = default;
|
||||
};
|
||||
|
||||
}</pre>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>intrusive_ref_counter();</pre>
|
||||
<blockquote>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> The pointer to the constructed object is expected to be passed to <STRONG>intrusive_ptr</STRONG>
|
||||
constructor, assignment operator or <STRONG>reset()</STRONG> method, which would increment the reference counter.</P>
|
||||
</blockquote>
|
||||
<pre>intrusive_ref_counter(intrusive_ref_counter const &);</pre>
|
||||
<blockquote>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> The pointer to the constructed object is expected to be passed to <STRONG>intrusive_ptr</STRONG>
|
||||
constructor, assignment operator or <STRONG>reset()</STRONG> method, which would increment the reference counter.</P>
|
||||
</blockquote>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~intrusive_ref_counter();</pre>
|
||||
<BLOCKQUOTE>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Effects:</B> Destroys the counter object.</P>
|
||||
<P><B>Notes:</B> The destructor is protected so that the object can only be destroyed through the <STRONG>DerivedT</STRONG> class.</P>
|
||||
</BLOCKQUOTE>
|
||||
<H3><a name="assignment">assignment</a></H3>
|
||||
<pre>intrusive_ref_counter & operator=(intrusive_ref_counter const & r) noexcept;</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Does nothing, reference counter is not modified.</P>
|
||||
<P><B>Returns:</B> <code>*this</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<H3><a name="use_count">use_count</a></H3>
|
||||
<pre>unsigned int use_count() const noexcept;</pre>
|
||||
<BLOCKQUOTE>
|
||||
<p><b>Returns:</b> The current value of the reference counter.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> The returned value may not be actual in multi-threaded applications.</P>
|
||||
</BLOCKQUOTE>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p>
|
||||
<small>Copyright © 2013 Andrey Semashev. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
119
make_shared.html
119
make_shared.html
@ -1,119 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>make_shared and allocate_shared</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">make_shared and allocate_shared
|
||||
function templates</h1>
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#functions">Free Functions</A><br>
|
||||
<A href="#example">Example</A><br>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>Consistent use of <a href="shared_ptr.htm"><code>shared_ptr</code></a>
|
||||
can eliminate the need to use an explicit <code>delete</code>,
|
||||
but alone it provides no support in avoiding explicit <code>new</code>.
|
||||
There have been repeated requests from users for a factory function that creates
|
||||
an object of a given type and returns a <code>shared_ptr</code> to it.
|
||||
Besides convenience and style, such a function is also exception safe and
|
||||
considerably faster because it can use a single allocation for both the object
|
||||
and its corresponding control block, eliminating a significant portion of
|
||||
<code>shared_ptr</code>'s construction overhead.
|
||||
This eliminates one of the major efficiency complaints about <code>shared_ptr</code>.
|
||||
</p>
|
||||
<p>The header file <boost/make_shared.hpp> provides a family of overloaded function templates,
|
||||
<code>make_shared</code> and <code>allocate_shared</code>, to address this need.
|
||||
<code>make_shared</code> uses the global operator <code>new</code> to allocate memory,
|
||||
whereas <code>allocate_shared</code> uses an user-supplied allocator, allowing finer control.</p>
|
||||
<p>
|
||||
The rationale for choosing the name <code>make_shared</code> is that the expression
|
||||
<code>make_shared<Widget>()</code> can be read aloud and conveys the intended meaning.</p>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
template<typename T> class shared_ptr;
|
||||
|
||||
template<typename T>
|
||||
shared_ptr<T> <a href="#functions">make_shared</a>();
|
||||
|
||||
template<typename T, typename A>
|
||||
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & );
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) // C++0x prototypes
|
||||
|
||||
template<typename T, typename... Args>
|
||||
shared_ptr<T> <a href="#functions">make_shared</a>( Args && ... args );
|
||||
|
||||
template<typename T, typename A, typename... Args>
|
||||
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & a, Args && ... args );
|
||||
|
||||
#else // no C++0X support
|
||||
|
||||
template<typename T, typename Arg1 >
|
||||
shared_ptr<T> <a href="#functions">make_shared</a>( Arg1 const & arg1 );
|
||||
template<typename T, typename Arg1, typename Arg2 >
|
||||
shared_ptr<T> <a href="#functions">make_shared</a>( Arg1 const & arg1, Arg2 const & arg2 );
|
||||
// ...
|
||||
template<typename T, typename Arg1, typename Arg2, ..., typename ArgN >
|
||||
shared_ptr<T> <a href="#functions">make_shared</a>( Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );
|
||||
|
||||
template<typename T, typename A, typename Arg1 >
|
||||
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & a, Arg1 const & arg1 );
|
||||
template<typename T, typename A, typename Arg1, typename Arg2 >
|
||||
shared_ptr<T> <a href="#functions">allocate_shared</a>( Arg1 const & arg1, Arg2 const & arg2 );
|
||||
// ...
|
||||
template<typename T, typename A, typename Arg1, typename Arg2, ..., typename ArgN >
|
||||
shared_ptr<T> <a href="#functions">allocate_shared</a>( A const & a, Arg1 const & arg1, Arg2 const & arg2, ..., ArgN const & argN );
|
||||
|
||||
#endif
|
||||
}</pre>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<pre>template<class T, class... Args>
|
||||
shared_ptr<T> make_shared( Args && ... args );
|
||||
template<class T, class A, class... Args>
|
||||
shared_ptr<T> allocate_shared( A const & a, Args && ... args );</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>new( pv ) T( std::forward<Args>(args)... )</code>,
|
||||
where <code>pv</code> is a <code>void*</code> pointing to storage suitable
|
||||
to hold an object of type <code>T</code>,
|
||||
shall be well-formed. <code>A</code> shall be an <em>Allocator</em>,
|
||||
as described in section 20.1.5 (<strong>Allocator requirements</strong>) of the C++ Standard.
|
||||
The copy constructor and destructor of <code>A</code> shall not throw.</p>
|
||||
<p><b>Effects:</b> Allocates memory suitable for an object of type <code>T</code>
|
||||
and constructs an object in it via the placement new expression <code>new( pv ) T()</code>
|
||||
or <code>new( pv ) T( std::forward<Args>(args)... )</code>.
|
||||
<code>allocate_shared</code> uses a copy of <code>a</code> to allocate memory.
|
||||
If an exception is thrown, has no effect.</p>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and owns the address
|
||||
of the newly constructed object of type <code>T</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>get() != 0 && use_count() == 1</code>.</p>
|
||||
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from <code>A::allocate</code>
|
||||
or the constructor of <code>T</code>.</p>
|
||||
<p><b>Notes:</b> This implementation allocates the memory required for the
|
||||
returned <code>shared_ptr</code> and an object of type <code>T</code> in a single
|
||||
allocation. This provides efficiency equivalent to an intrusive smart pointer.</p>
|
||||
<p>The prototypes shown above are used if your compiler supports rvalue references
|
||||
and variadic templates. They perfectly forward the <code>args</code> parameters to
|
||||
the constructors of <code>T</code>.</p>
|
||||
<p>Otherwise, the implementation will fall back on
|
||||
forwarding the arguments to the constructors of <code>T</code> as const references.
|
||||
If you need to pass a non-const reference to a constructor of <code>T</code>,
|
||||
you may do so by wrapping the parameter in a call to <code>boost::ref</code>.
|
||||
In addition, you will be
|
||||
limited to a maximum of 9 arguments (not counting the allocator argument of
|
||||
allocate_shared).</p>
|
||||
</blockquote>
|
||||
<h2><a name="example">Example</a></h2>
|
||||
<pre>boost::shared_ptr<std::string> x = boost::make_shared<std::string>("hello, world!");
|
||||
std::cout << *x;</pre>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess.
|
||||
Distributed under the Boost Software License,
|
||||
Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
|
||||
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
@ -1,393 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>allocate_shared and make_shared for arrays</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>allocate_shared and make_shared for arrays</h1>
|
||||
<div id="navigation">
|
||||
<ul>
|
||||
<li><a href="#introduction">Introduction</a></li>
|
||||
<li><a href="#synopsis">Synopsis</a></li>
|
||||
<li><a href="#requirements">Common Requirements</a></li>
|
||||
<li><a href="#functions">Free Functions</a></li>
|
||||
<li><a href="#history">History</a></li>
|
||||
<li><a href="#references">References</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="introduction">
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
Originally the Boost function templates <code>allocate_shared</code> and
|
||||
<code>make_shared</code> were for efficient allocation of shared scalar
|
||||
objects only. There was a need to have efficient allocation of shared
|
||||
arrays. One criticism of class template <code>shared_array</code>
|
||||
was always the lack of a utility like <code>make_shared</code> that
|
||||
uses only a single allocation.
|
||||
</p>
|
||||
<p>
|
||||
The header files <boost/smart_ptr/allocate_shared_array.hpp> and
|
||||
<boost/smart_ptr/make_shared_array.hpp> provide function
|
||||
templates, overloads of <code>allocate_shared</code> and
|
||||
<code>make_shared</code> for array types, to address this need.
|
||||
<code>allocate_shared</code> uses a user-supplied allocator for
|
||||
allocation, while <code>make_shared</code> uses
|
||||
<code>allocate_shared</code> with the Default Allocator.
|
||||
</p>
|
||||
</div>
|
||||
<div id="synopsis">
|
||||
<h2>Synopsis</h2>
|
||||
<div>
|
||||
<h3>Header <boost/smart_ptr/allocate_shared_array.hpp></h3>
|
||||
<code>namespace boost {</code>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">allocate_shared</a>(const A& a,
|
||||
std::size_t n);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">allocate_shared</a>(const A& a);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">allocate_shared</a>(const A& a, std::size_t n,
|
||||
const <em>E</em>& v);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">allocate_shared</a>(const A& a,
|
||||
const <em>E</em>& v);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">allocate_shared_noinit</a>(const A& a,
|
||||
std::size_t n);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">allocate_shared_noinit</a>(const A& a);</code>
|
||||
</blockquote>
|
||||
<code>}</code>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Header <boost/smart_ptr/make_shared_array.hpp></h3>
|
||||
<code>namespace boost {</code>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">make_shared</a>(std::size_t n);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">make_shared</a>();</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">make_shared</a>(std::size_t n,
|
||||
const <em>E</em>& v);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">make_shared</a>(const <em>E</em>& v);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">make_shared_noinit</a>(std::size_t n);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class A><br>shared_ptr<T>
|
||||
<a href="#functions">make_shared_noinit</a>();</code>
|
||||
</blockquote>
|
||||
<code>}</code>
|
||||
</div>
|
||||
</div>
|
||||
<div id="requirements">
|
||||
<h2>Common Requirements</h2>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared(const A& a, <em>args</em>);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Requires:</strong></dt>
|
||||
<dd><code>T</code> is of the form <code>E[N]</code> or
|
||||
<code>E[]</code>. <code>A</code> shall be an <em>Allocator</em>, as
|
||||
described in section 17.6.3.5 [Allocator requirements] of the C++
|
||||
Standard. The copy constructor and destructor of <code>A</code> shall
|
||||
not throw exceptions.</dd>
|
||||
<dt><strong>Effects:</strong></dt>
|
||||
<dd>Allocates storage for an object of type <code>E</code> (or
|
||||
<code>E[size]</code> when <code>T</code> is <code>E[]</code>, where
|
||||
<code>size</code> is determined from <code>args</code> as specified by
|
||||
the concrete overload). A copy of the allocator is used to allocate
|
||||
storage. The storage is initialized as specified by the concrete
|
||||
overload. If an exception is thrown, the functions have no effect.</dd>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> instance that stores and owns the address
|
||||
of the newly allocated and constructed object.</dd>
|
||||
<dt><strong>Postconditions:</strong></dt>
|
||||
<dd><code>r.get() != 0</code> and <code>r.use_count() == 1</code>,
|
||||
where <code>r</code> is the return value.</dd>
|
||||
<dt><strong>Throws:</strong></dt>
|
||||
<dd>An exception thrown from <code>A::allocate()</code>, or from the
|
||||
initialization of the object.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>This implementation performs no more than one memory allocation.
|
||||
This provides efficiency to equivalent to an intrusive smart
|
||||
pointer.</li>
|
||||
<li>When an object of an array type <code>T</code> is specified to be
|
||||
initialized to a value of the same type <code>v</code>, this shall be
|
||||
interpreted to mean that each array element of the object is initialized
|
||||
to the corresponding element from <code>v</code>.</li>
|
||||
<li>When an object of an array type <code>T</code> is specified to be
|
||||
value-initialized, this shall be interpreted to mean that each array
|
||||
element of the object is value-initialized.</li>
|
||||
<li>Array elements are initialized in ascending order of their
|
||||
addresses.</li>
|
||||
<li>When a subobject of a scalar type <code>S</code> is specified to
|
||||
be initialized to a value <code>v</code>, <code>allocate_shared</code>
|
||||
shall perform this initialization via the expression
|
||||
<code>std::allocator_traits<A>::construct(b, p, v)</code>, where
|
||||
<code>p</code> points to storage suitable to hold an object of type
|
||||
<code>S</code> and <code>b</code> of is a copy of the allocator
|
||||
<code>a</code> passed to <code>allocate_shared</code> such that its
|
||||
<code>value_type</code> is <code>S</code>.</li>
|
||||
<li>When a subobject of scalar type <code>S</code> is specified to be
|
||||
value-initialized, <code>allocate_shared</code> shall perform this
|
||||
initialization via the expression
|
||||
<code>std::allocator_traits<A>::construct(b, p)</code>, where
|
||||
<code>p</code> points to storage suitable to hold an object
|
||||
of type <code>S</code> and <code>b</code> is a copy of the allocator
|
||||
<code>a</code> passed to <code>allocate_shared</code> such that its
|
||||
<code>value_type</code> is <code>S</code>.</li>
|
||||
<li>When a subobject of scalar type <code>S</code> is specified to be
|
||||
default-initialized, <code>allocate_shared_noinit</code> shall perform
|
||||
this initialization via the expression <code>::new(p) S</code>, where
|
||||
<code>p</code> has type <code>void*</code> and points to storage
|
||||
suitable to hold an object of type <code>S</code>.</li>
|
||||
<li>When the lifetime of the object managed by the return value ends,
|
||||
or when the initialization of an array element throws an exception,
|
||||
the initialized elements should be destroyed in the reverse order
|
||||
of their construction.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt><strong>Notes:</strong></dt>
|
||||
<dd>These functions will typically allocate more memory than the size of
|
||||
<code>sizeof(E)</code> to allow for internal bookkeeping structures such
|
||||
as the reference counts.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="functions">
|
||||
<h2>Free Functions</h2>
|
||||
<div>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared(const A& a, std::size_t n);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> to a value-initialized object of type
|
||||
<code>E[size]</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::allocate_shared<int[]<!--
|
||||
-->>(std::allocator<int>(), 8);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared(const A& a);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> to a value-initialized object of type
|
||||
<code>E[N]</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[N]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::allocate_shared<int[8]<!--
|
||||
-->>(std::allocator<int>());</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared(const A& a, std::size_t n,
|
||||
const <em>E</em>& v);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> to an object of type
|
||||
<code>E[size]</code>, where each array element of type <code>E</code> is
|
||||
initialized to <code>v</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::allocate_shared<double[]<!--
|
||||
-->>(std::allocator<double>(), 8, 1.0);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared(const A& a, const <em>E</em>& v);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> to an object of type <code>E[N]</code>,
|
||||
where each array element of type <code>E</code> is initialized to
|
||||
<code>v</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[N]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::allocate_shared<double[8]<!--
|
||||
-->>(std::allocator<double>(), 1.0);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared_noinit(const A& a, std::size_t n);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> to a default-initialized object of type
|
||||
<code>E[size]</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::allocate_shared_noinit<int[]<!--
|
||||
-->>(std::allocator<int>(), 8);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T, class A><br>shared_ptr<T>
|
||||
allocate_shared_noinit(const A& a);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>shared_ptr</code> to a default-initialized object of type
|
||||
<code>E[N]</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[N]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::allocate_shared_noinit<int[8]<!--
|
||||
-->>(std::allocator<int>());</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>shared_ptr<T>
|
||||
make_shared(std::size_t n);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd><code>allocate_shared<T>(std::allocator<<em>S<!--
|
||||
--></em>>(), n);</code></dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_shared<int[]>(8);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>shared_ptr<T>
|
||||
make_shared();</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd><code>allocate_shared<T>(std::allocator<<em>S<!--
|
||||
--></em>>());</code></dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[N]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_shared<int[8]>();</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>shared_ptr<T>
|
||||
make_shared(std::size_t n, const <em>E</em>& v);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd><code>allocate_shared<T>(std::allocator<<em>S<!--
|
||||
--></em>>(), n, v);</code></dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_shared<double[]>(8, 1.0);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>shared_ptr<T>
|
||||
make_shared(const <em>E</em>& v);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd><code>allocate_shared<T>(std::allocator<<em>S<!--
|
||||
--></em>>(), v);</code></dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[N].</code></dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_shared<double[8]>(1.0);</code></dd></dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>shared_ptr<T>
|
||||
make_shared_noinit(std::size_t n);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd><code>allocate_shared_noinit<T>(std::allocator<<em>S<!--
|
||||
--></em>>(), n);</code></dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_shared_noinit<int[]>(8);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>shared_ptr<T>
|
||||
make_shared_noinit();</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd><code>allocate_shared_noinit<T>(std::allocator<<em>S<!--
|
||||
--></em>>());</code></dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[N]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_shared_noinit<int[8]>();</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div id="history">
|
||||
<h2>History</h2>
|
||||
<dl>
|
||||
<dt><strong>Boost 1.64</strong></dt>
|
||||
<dd>Glen Fernandes rewrote allocate_shared and make_shared for a more
|
||||
optimal and more maintainable implementation.</dd>
|
||||
<dt><strong>Boost 1.56</strong></dt>
|
||||
<dd>Glen Fernandes updated overloads of make_shared and allocate_shared
|
||||
to conform to the specification in C++ standard paper
|
||||
<a href="#N3870">N3870</a>, including resolving C++ standard library
|
||||
defect report <a href="#dr2070">DR 2070</a>.</dd>
|
||||
<dt><strong>Boost 1.53</strong></dt>
|
||||
<dd>Glen Fernandes contributed implementations of make_shared and
|
||||
allocate_shared for arrays.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="references">
|
||||
<h2>References</h2>
|
||||
<ol>
|
||||
<li id="N3870"><strong>N3870</strong>, <a href=
|
||||
"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html">
|
||||
Extending make_shared to Support Arrays, Revision 1</a>, Peter Dimov
|
||||
& Glen Fernandes, January, 2014.</li>
|
||||
<li id="dr2070"><strong>DR 2070</strong>,
|
||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html">
|
||||
allocate_shared should use allocator_traits<A>::construct</a>,
|
||||
Jonathan Wakely, July, 2011.</li>
|
||||
</ol>
|
||||
</div>
|
||||
<hr>
|
||||
Copyright 2012-2017 Glen Fernandes. Distributed under the
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License,
|
||||
Version 1.0</a>.
|
||||
</body>
|
||||
</html>
|
184
make_unique.html
184
make_unique.html
@ -1,184 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>make_unique</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>make_unique</h1>
|
||||
<div id="navigation">
|
||||
<ul>
|
||||
<li><a href="#introduction">Introduction</a></li>
|
||||
<li><a href="#synopsis">Synopsis</a></li>
|
||||
<li><a href="#requirements">Common Requirements</a></li>
|
||||
<li><a href="#functions">Free Functions</a></li>
|
||||
<li><a href="#history">History</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="introduction">
|
||||
<h2>Introduction</h2>
|
||||
<p>
|
||||
The header file <boost/make_unique.hpp> provides overloads of
|
||||
function template <code>make_unique</code> for convenient creation of
|
||||
<code>std::unique_ptr</code> objects.
|
||||
</p>
|
||||
</div>
|
||||
<div id="synopsis">
|
||||
<h2>Synopsis</h2>
|
||||
<div>
|
||||
<h3>Header <boost/smart_ptr/make_unique.hpp></h3>
|
||||
<code>namespace boost {</code>
|
||||
<blockquote>
|
||||
<code>template<class T><br>std::unique_ptr<T>
|
||||
<a href="#functions">make_unique</a>();</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T, class... Args><br>std::unique_ptr<T>
|
||||
<a href="#functions">make_unique</a>(Args&&... args);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T><br>std::unique_ptr<T>
|
||||
<a href="#functions">make_unique</a>(<em>T</em>&& value);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T><br>std::unique_ptr<T>
|
||||
<a href="#functions">make_unique</a>(std::size_t size);</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T><br>std::unique_ptr<T>
|
||||
<a href="#functions">make_unique_noinit</a>();</code>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<code>template<class T><br>std::unique_ptr<T>
|
||||
<a href="#functions">make_unique_noinit</a>(std::size_t size);</code>
|
||||
</blockquote>
|
||||
<code>}</code>
|
||||
</div>
|
||||
</div>
|
||||
<div id="requirements">
|
||||
<h2>Common Requirements</h2>
|
||||
<h3><code>template<class T, <em>Args</em>><br>
|
||||
std::unique_ptr<T> make_unique(<em>args</em>);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Effects:</strong></dt>
|
||||
<dd>Allocates storage for an object of type <code>T</code> (or
|
||||
<code>E[size]</code> when <code>T</code> is <code>E[]</code>, where
|
||||
<code>size</code> is determined from <code>args</code> as specified by
|
||||
the concrete overload). The storage is initialized from
|
||||
<code>args</code> as specified by the concrete overload. If an exception
|
||||
is thrown, the functions have no effect.</dd>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>std::unique_ptr</code> instance that stores and owns the
|
||||
address of the newly allocated and constructed object.</dd>
|
||||
<dt><strong>Postconditions:</strong></dt>
|
||||
<dd><code>r.get() != 0</code>, where <code>r</code> is the return
|
||||
value.</dd>
|
||||
<dt><strong>Throws:</strong></dt>
|
||||
<dd><code>std::bad_alloc</code>, or an exception thrown from the
|
||||
initialization of the object.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>When an object of a scalar type T is specified to be initialized to
|
||||
a value <code>value</code>, or to <code>T(args...)</code>, where
|
||||
<code>args...</code> is a list of constructor arguments,
|
||||
<code>make_unique</code> shall perform this initialization via the
|
||||
expression <code>new T(value)</code> or <code>new T(args...)</code>
|
||||
respectively.</li>
|
||||
<li>When an object of type <code>T</code> is specified to be
|
||||
value-initialized, <code>make_unique</code> shall perform this
|
||||
initialization via the expression <code>new T()</code>.</li>
|
||||
<li>When an object of type <code>T</code> is specified to be
|
||||
default-initialized, <code>make_unique_noinit</code> shall perform this
|
||||
initialization via the expression <code>new T</code>.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div id="functions">
|
||||
<h2>Free functions</h2>
|
||||
<div>
|
||||
<h3><code>template<class T, class... Args><br>
|
||||
std::unique_ptr<T>
|
||||
make_unique(Args&&... args);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>std::unique_ptr</code> to an object of type <code>T</code>,
|
||||
initialized to <code>std::forward<Args>(args)...</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is not an array type.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_unique<double>(1.0);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>std::unique_ptr<T>
|
||||
make_unique(<em>T</em>&& value);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>std::unique_ptr</code> to an object of type <code>T</code>,
|
||||
initialized to <code>std::move(value)</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is not an array type.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_unique<point>({1.0, -1.0});</code></dd></dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>std::unique_ptr<T>
|
||||
make_unique(std::size_t size);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>std::unique_ptr</code> to a value-initialized object of type
|
||||
<code>E[size]</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_unique<int[]>(8);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>std::unique_ptr<T>
|
||||
make_unique_noinit();</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>std::unique_ptr</code> to a default-initialized object of
|
||||
type <code>T</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is not an array type.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_unique_noinit<std::tm>();</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<h3><code>template<class T><br>std::unique_ptr<T>
|
||||
make_unique_noinit(std::size_t size);</code></h3>
|
||||
<dl>
|
||||
<dt><strong>Returns:</strong></dt>
|
||||
<dd>A <code>std::unique_ptr</code> to a default-initialized object of
|
||||
type <code>E[size]</code>.</dd>
|
||||
<dt><strong>Remarks:</strong></dt>
|
||||
<dd>This overload shall only participate in overload resolution when
|
||||
<code>T</code> is of the form <code>E[]</code>.</dd>
|
||||
<dt><strong>Example:</strong></dt>
|
||||
<dd><code>boost::make_unique_noinit<char[]>(64);</code></dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div id="history">
|
||||
<h2>History</h2>
|
||||
<dl>
|
||||
<dt><strong>Boost 1.56</strong></dt>
|
||||
<dd>Glen Fernandes contributed implementations of make_unique for
|
||||
scalars and arrays</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<hr>
|
||||
Copyright 2012-2014 Glen Fernandes. Distributed under the
|
||||
<a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License,
|
||||
Version 1.0</a>.
|
||||
</body>
|
||||
</html>
|
BIN
msvcspeed.gif
BIN
msvcspeed.gif
Binary file not shown.
Before Width: | Height: | Size: 6.0 KiB |
@ -1,183 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>pointer_cast</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0" />pointer_cast</h1>
|
||||
<p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code>
|
||||
<code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>)
|
||||
provide a way to write generic pointer castings for raw pointers, <code>std::shared_ptr</code> and <code>std::unique_ptr</code>. The functions
|
||||
are defined in <cite><a href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</a>.</cite></p>
|
||||
<p>There is test/example code in <cite><a href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</a></cite>.</p>
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
<P>Boost smart pointers usually overload those functions to provide a mechanism to
|
||||
emulate pointers casts. For example, <code>boost::shared_ptr<...></code> implements
|
||||
a static pointer cast this way:</P>
|
||||
<pre>
|
||||
template<class T, class U>
|
||||
shared_ptr<T> static_pointer_cast(shared_ptr<U> const &r);
|
||||
</pre>
|
||||
<p>Pointer cast functions from <cite><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE>
|
||||
are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>,
|
||||
<code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code>
|
||||
for raw pointers, <code>std::shared_ptr</code> and <code>std::unique_ptr</code>. 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.</p>
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
<blockquote>
|
||||
<pre>
|
||||
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
|
||||
</pre>
|
||||
</blockquote>
|
||||
<p>As you can see from the above synopsis, the pointer cast functions for raw pointers are just
|
||||
wrappers around standard C++ cast operators.</p>
|
||||
|
||||
<p>The pointer casts for <code>std::shared_ptr</code> are aliases of the corresponding standard
|
||||
functions with the same names and equivalent to <a href="shared_ptr.htm#static_pointer_cast">the
|
||||
functions taking <code>boost::shared_ptr</code></a>.</p>
|
||||
|
||||
<p>The pointer casts for <code>std::unique_ptr</code> are documented below.</p>
|
||||
|
||||
<h3 id="static_pointer_cast">static_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
unique_ptr<T> static_pointer_cast(unique_ptr<U>&& r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>static_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b> <code>unique_ptr<T>( static_cast<typename unique_ptr<T>::element_type*>(r.release()) )</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> the seemingly equivalent expression
|
||||
<code>unique_ptr<T>(static_cast<T*>(r.get()))</code>
|
||||
will eventually result in undefined behavior, attempting to delete the same
|
||||
object twice.</p>
|
||||
</blockquote>
|
||||
<h3 id="const_pointer_cast">const_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
unique_ptr<T> const_pointer_cast(unique_ptr<U>&& r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>const_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b> <code>unique_ptr<T>( const_cast<typename unique_ptr<T>::element_type*>(r.release()) )</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="dynamic_pointer_cast">dynamic_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
unique_ptr<T> dynamic_pointer_cast(unique_ptr<U>&& r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>dynamic_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed. <code>T</code> must have a virtual destructor.</p>
|
||||
<p><b>Returns:</b></p>
|
||||
<ul>
|
||||
<li>
|
||||
When <code>dynamic_cast<typename unique_ptr<T>::element_type*>(r.get())</code> returns a nonzero value,
|
||||
<code>unique_ptr<T>(dynamic_cast<typename unique_ptr<T>::element_type*>(r.release()))</code>;</li>
|
||||
<li>
|
||||
Otherwise, <code>unique_ptr<T>()</code>.</li></ul>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="reinterpret_pointer_cast">reinterpret_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
unique_ptr<T> reinterpret_pointer_cast(unique_ptr<U>&& r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>reinterpret_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b> <code>unique_ptr<T>( reinterpret_cast<typename unique_ptr<T>::element_type*>(r.release()) )</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
|
||||
<h2><a name="example">Example</a></h2>
|
||||
<blockquote>
|
||||
<pre>
|
||||
#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()
|
||||
{
|
||||
<em>// Create a raw and a shared_ptr</em>
|
||||
|
||||
base *ptr = new derived;
|
||||
boost::shared_ptr<base> sptr(new derived);
|
||||
|
||||
<em>// Check that base pointer points actually to derived class</em>
|
||||
|
||||
check_if_it_is_derived(ptr);
|
||||
check_if_it_is_derived(sptr);
|
||||
|
||||
<em>// Ok!</em>
|
||||
|
||||
delete ptr;
|
||||
return 0;
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<p>The example demonstrates how the generic pointer casts help us create pointer
|
||||
independent code.</p>
|
||||
<hr />
|
||||
<p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to
|
||||
the Boost Software License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
|
||||
LICENSE_1_0.txt</a> or a copy at <<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p>
|
||||
</body>
|
||||
</html>
|
@ -1,108 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>pointer_to_other</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">pointer_to_other</h1>
|
||||
<p>
|
||||
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 <cite><a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a>.</cite></p>
|
||||
<p>There is test/example code in <cite><a href="test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a></cite>.</p>
|
||||
<h2><a name="contents">Contents</a></h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#rationale">Rationale</a>
|
||||
<li>
|
||||
<a href="#synopsis">Synopsis</a>
|
||||
<li>
|
||||
<a href="#example">Example</a></li>
|
||||
</ul>
|
||||
<h2><a name="rationale">Rationale</a></h2>
|
||||
<p>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.)</p>
|
||||
<pre>template <class IntPtr>
|
||||
class FloatPointerHolder
|
||||
{
|
||||
<em>// Let's define a pointer to a float</em>
|
||||
typedef typename boost::pointer_to_other
|
||||
<IntPtr, float>::type float_ptr_t;
|
||||
float_ptr_t float_ptr;
|
||||
};</pre>
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
<pre>
|
||||
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;
|
||||
};
|
||||
|
||||
} <em>// namespace boost</em></pre>
|
||||
<p>If these definitions are not correct for a specific smart pointer, we can define
|
||||
a specialization of pointer_to_other.</p>
|
||||
<h2><a name="example">Example</a></h2>
|
||||
<pre><em>// Let's define a memory allocator that can
|
||||
// work with raw and smart pointers</em>
|
||||
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
|
||||
template <class VoidPtr>
|
||||
class memory_allocator
|
||||
{<em>
|
||||
// Predefine a memory_block </em>
|
||||
struct block;<em>
|
||||
|
||||
// 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></em>
|
||||
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;
|
||||
};</pre>
|
||||
<p>As we can see, using pointer_to_other we can create pointer independent code.</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>Copyright 2005, 2006 Ion Gazta<74>aga and Peter Dimov. Use, modification,
|
||||
and distribution are subject to the Boost Software License, Version 1.0.<br>
|
||||
(See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a
|
||||
copy at < <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</small></p>
|
||||
</body>
|
||||
</html>
|
115
scoped_array.htm
115
scoped_array.htm
@ -1,115 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>scoped_array</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">scoped_array class template</h1>
|
||||
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically
|
||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
|
||||
expression.) The array pointed to is guaranteed to be deleted, either on
|
||||
destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
|
||||
<p>The <b>scoped_array</b> 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 <a href="../utility/utility.htm#Class_noncopyable">
|
||||
noncopyable</a>) signal its intent to retain ownership solely within the
|
||||
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
|
||||
it is safer than <b>shared_array</b> for pointers which should not be copied.</p>
|
||||
<p>Because <b>scoped_array</b> 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.</p>
|
||||
<p>It cannot be used in C++ standard library containers. See <a href="shared_array.htm">
|
||||
<b>shared_array</b></a> if <b>scoped_array</b> does not meet your needs.</p>
|
||||
<p>It cannot correctly hold a pointer to a single object. See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
|
||||
for that usage.</p>
|
||||
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is a bit
|
||||
heavier duty but far more flexible. A <b>boost::array</b> is an alternative
|
||||
that does not use dynamic allocation.</p>
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||
common requirements</a>.</p>
|
||||
<h2>Synopsis</h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
template<class T> class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws
|
||||
<a href="#destructor">~scoped_array</a>(); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
|
||||
T & <a href="#operator[]">operator[]</a>(std::ptrdiff_t i) const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(scoped_array & b); // never throws
|
||||
};
|
||||
|
||||
template<class T> void <a href="#free-swap">swap</a>(scoped_array<T> & a, scoped_array<T> & b); // never throws
|
||||
|
||||
}</pre>
|
||||
<h2>Members</h2>
|
||||
<h3>
|
||||
<a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="ctor">constructors</a></h3>
|
||||
<pre>explicit scoped_array(T * p = 0); // never throws</pre>
|
||||
<p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must have
|
||||
been allocated via a C++ <b>new</b>[] expression or be 0. <b>T</b> is not
|
||||
required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||
common requirements</a>.</p>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~scoped_array(); // never throws</pre>
|
||||
<p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> 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 <a href="smart_ptr.htm#common_requirements">
|
||||
common requirements</a>.</p>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(T * p = 0); // never throws</pre>
|
||||
<p>
|
||||
Deletes the array pointed to by the stored pointer and then stores a copy of p,
|
||||
which must have been allocated via a C++ <b>new[]</b> 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 <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="operator[]">subscripting</a></h3>
|
||||
<pre>T & operator[](std::ptrdiff_t i) const; // never throws</pre>
|
||||
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
|
||||
pointer. Behavior is undefined and almost certainly undesirable if the stored
|
||||
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
|
||||
number of elements in the array.</p>
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
|
||||
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||
to <code>get() != 0</code>.</p>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(scoped_array & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
|
||||
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>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 <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
180
scoped_ptr.htm
180
scoped_ptr.htm
@ -1,180 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>scoped_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">scoped_ptr class template</h1>
|
||||
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
|
||||
The object pointed to is guaranteed to be deleted, either on destruction of the <b>scoped_ptr</b>,
|
||||
or via an explicit <b>reset</b>. See the <a href="#example">example</a>.</p>
|
||||
<p>The <b>scoped_ptr</b> 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 <a href="../utility/utility.htm#Class_noncopyable">
|
||||
noncopyable</a>) signal its intent to retain ownership solely within the
|
||||
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
|
||||
it is safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which
|
||||
should not be copied.</p>
|
||||
<p>Because <b>scoped_ptr</b> 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.</p>
|
||||
<p><STRONG>scoped_ptr</STRONG> cannot be used in C++ Standard Library containers.
|
||||
Use <a href="shared_ptr.htm"><b>shared_ptr</b></a> if you need a smart pointer
|
||||
that can.</p>
|
||||
<p><STRONG>scoped_ptr</STRONG> cannot correctly hold a pointer to a dynamically
|
||||
allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a> for
|
||||
that usage.</p>
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||
common requirements</a>.</p>
|
||||
<h2>Synopsis</h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
template<class T> class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws
|
||||
<a href="#destructor">~scoped_ptr</a>(); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(scoped_ptr & b); // never throws
|
||||
};
|
||||
|
||||
template<class T> void <a href="#free-swap">swap</a>(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
|
||||
|
||||
}</pre>
|
||||
<h2>Members</h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>explicit scoped_ptr(T * p = 0); // never throws</pre>
|
||||
<p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must have been
|
||||
allocated via a C++ <b>new</b> expression or be 0. <b>T</b> is not required be
|
||||
a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||
requirements</a>.</p>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~scoped_ptr(); // never throws</pre>
|
||||
<p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete
|
||||
this->get()</tt>.</p>
|
||||
<P>
|
||||
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 <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(T * p = 0); // never throws</pre>
|
||||
<p>
|
||||
Deletes the object pointed to by the stored pointer and then stores a copy of
|
||||
p, which must have been allocated via a C++ <b>new</b> 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 <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer. Behavior is
|
||||
undefined if the stored pointer is 0.</p>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
|
||||
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||
to <code>get() != 0</code>.</p>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(scoped_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
|
||||
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
<h2><a name="example">Example</a></h2>
|
||||
<p>Here's an example that uses <b>scoped_ptr</b>.</p>
|
||||
<blockquote>
|
||||
<pre>#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';
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<p>The example program produces the beginning of a child's nursery rhyme:</p>
|
||||
<blockquote>
|
||||
<pre>1
|
||||
2
|
||||
Buckle my shoe</pre>
|
||||
</blockquote>
|
||||
<h2>Rationale</h2>
|
||||
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> 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.</p>
|
||||
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance
|
||||
programmer from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
|
||||
because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership
|
||||
could safely be transferred.</p>
|
||||
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b>
|
||||
is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b>
|
||||
in the C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>,
|
||||
you tell your readers what your intent is. Same with <b>scoped_ptr</b>; by
|
||||
using it you are signaling intent.</p>
|
||||
<p>It has been suggested that <b>scoped_ptr<T></b> is equivalent to <b>std::auto_ptr<T>
|
||||
const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on
|
||||
a <b>std::auto_ptr<T> const.</b></p>
|
||||
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
|
||||
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called
|
||||
pimpl) idiom which avoids exposing the body (implementation) in the header
|
||||
file.</p>
|
||||
<p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
|
||||
sample program includes a header file, <a href="example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
|
||||
which uses a <b>scoped_ptr<></b> to an incomplete type to hide the
|
||||
implementation. The instantiation of member functions which require a complete
|
||||
type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
|
||||
implementation file.</p>
|
||||
<h2>Frequently Asked Questions</h2>
|
||||
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
|
||||
<b>A</b>. When reading source code, it is valuable to be able to draw
|
||||
conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG>
|
||||
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 <STRONG>std::auto_ptr</STRONG> where transfer of ownership
|
||||
is required. (supplied by Dave Abrahams)</p>
|
||||
<hr>
|
||||
<p>$Date</p>
|
||||
<p><small>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 <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
183
shared_array.htm
183
shared_array.htm
@ -1,183 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>shared_array</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">shared_array class template</h1>
|
||||
<p>The <b>shared_array</b> class template stores a pointer to a dynamically
|
||||
allocated array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
|
||||
expression.) The object pointed to is guaranteed to be deleted when the last <b>shared_array</b>
|
||||
pointing to it is destroyed or reset.</p>
|
||||
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
|
||||
requirements of the C++ Standard Library, and so can be used in standard
|
||||
library containers. Comparison operators are supplied so that <b>shared_array</b>
|
||||
works with the standard library's associative containers.</p>
|
||||
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to an object
|
||||
that has been allocated with the non-array form of <STRONG>new</STRONG>. See <a href="shared_ptr.htm">
|
||||
<b>shared_ptr</b></a> for that usage.</p>
|
||||
<p>Because the implementation uses reference counting, cycles of <b>shared_array</b>
|
||||
instances will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_array</b>
|
||||
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
|
||||
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
|
||||
will leave <b>A</b> dangling with a use count of 1.</p>
|
||||
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b>
|
||||
that is a bit heavier duty but far more flexible.</p>
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||
common requirements</a>.</p>
|
||||
<h2>Synopsis</h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
template<class T> class shared_array {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
explicit <a href="#constructors">shared_array</a>(T * p = 0);
|
||||
template<class D> <a href="#constructors">shared_array</a>(T * p, D d);
|
||||
<a href="#destructor">~shared_array</a>(); // never throws
|
||||
|
||||
<a href="#constructors">shared_array</a>(shared_array const & r); // never throws
|
||||
|
||||
shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0);
|
||||
template<class D> void <a href="#reset">reset</a>(T * p, D d);
|
||||
|
||||
T & <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
bool <a href="#unique">unique</a>() const; // never throws
|
||||
long <a href="#use_count">use_count</a>() const; // never throws
|
||||
|
||||
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(shared_array<T> & b); // never throws
|
||||
};
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<class T>
|
||||
bool <a href="#comparison">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<class T>
|
||||
bool <a href="#comparison">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
|
||||
template<class T> void <a href="#free-swap">swap</a>(shared_array<T> & a, shared_array<T> & b); // never throws
|
||||
|
||||
}</pre>
|
||||
<h2>Members</h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>explicit shared_array(T * p = 0);</pre>
|
||||
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which must be a
|
||||
pointer to an array that was allocated via a C++ <b>new[]</b> expression or be
|
||||
0. Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">
|
||||
~shared_array</a>). The only exception which may be thrown by this
|
||||
constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b>
|
||||
is called.</p>
|
||||
<pre>template<class D> shared_array(T * p, D d);</pre>
|
||||
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy
|
||||
constructor and destructor must not throw. When the the time comes to delete
|
||||
the array pointed to by <b>p</b>, the object <b>d</b> is used in the statement <b>d(p)</b>.
|
||||
Invoking the object <b>d</b> with parameter <b>p</b> in this way must not
|
||||
throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
<pre>shared_array(shared_array const & r); // never throws</pre>
|
||||
<p>Constructs a <b>shared_array</b>, as if by storing a copy of the pointer stored
|
||||
in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> for all copies
|
||||
is 1 more than the initial use count.</p>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~shared_array(); // never throws</pre>
|
||||
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
|
||||
deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
|
||||
a pointer with a value of 0 is harmless. <b>T</b> 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 <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="assignment">assignment</a></h3>
|
||||
<pre>shared_array & operator=(shared_array const & r); // never throws</pre>
|
||||
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_array</b> with the new one, destroying the
|
||||
replaced object.</p>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(T * p = 0);</pre>
|
||||
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_array</b> with the new one, destroying the
|
||||
replaced object. The only exception which may be thrown is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>delete[] p</b> is called.</p>
|
||||
<pre>template<class D> void reset(T * p, D d);</pre>
|
||||
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_array</b> with the new one, destroying the
|
||||
replaced object. <b>D</b>'s copy constructor must not throw. The only exception
|
||||
which may be thrown is <b>std::bad_alloc</b>. If an exception is thrown, <b>d(p)</b>
|
||||
is called.</p>
|
||||
<h3><a name="indexing">indexing</a></h3>
|
||||
<pre>T & operator[](std::ptrdiff_t i) const; // never throws</pre>
|
||||
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
|
||||
pointer. Behavior is undefined and almost certainly undesirable if the stored
|
||||
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
|
||||
number of elements in the array.</p>
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
|
||||
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="unique">unique</a></h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored
|
||||
pointer, false otherwise. <b>T</b> need not be a complete type. See the smart
|
||||
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_array</b> objects sharing ownership of the
|
||||
stored pointer. <b>T</b> need not be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
|
||||
common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>shared_array</b> 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.</p>
|
||||
<h3><a name="conversions">conversions</a></h3>
|
||||
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
|
||||
to <code>get() != 0</code>.</p>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
|
||||
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>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</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers. <b>T</b> need not be a
|
||||
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
|
||||
requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>shared_array</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>. The
|
||||
implementation uses <b>std::less<T *></b> 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 <b>std::less<></b> on pointers is well-defined (20.3.3
|
||||
[lib.comparisons] paragraph 8).</p>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<class T>
|
||||
void swap(shared_array<T> & a, shared_array<T> & b) // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>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 <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
858
shared_ptr.htm
858
shared_ptr.htm
@ -1,858 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>shared_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">shared_ptr class template</h1>
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#BestPractices">Best Practices</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#functions">Free Functions</a><br>
|
||||
<a href="#example">Example</a><br>
|
||||
<a href="#HandleBody">Handle/Body Idiom</a><br>
|
||||
<a href="#ThreadSafety">Thread Safety</a><br>
|
||||
<a href="#FAQ">Frequently Asked Questions</a><br>
|
||||
<a href="smarttests.htm">Smart Pointer Timings</a><br>
|
||||
<a href="sp_techniques.html">Programming Techniques</a></p>
|
||||
<h2 id="Introduction">Introduction</h2>
|
||||
<p>The <code>shared_ptr</code> class template stores a pointer to a dynamically allocated
|
||||
object, typically with a C++ <em>new-expression</em>. The object pointed to is
|
||||
guaranteed to be deleted when the last <code>shared_ptr</code> pointing to it is
|
||||
destroyed or reset.</p>
|
||||
<blockquote><em>Example:</em><br><pre>shared_ptr<X> p1( new X );
|
||||
shared_ptr<void> p2( new int(5) );
|
||||
</pre></blockquote>
|
||||
|
||||
<p><code>shared_ptr</code> 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 <code>p2</code> is destroyed or reset, it will call <code>delete</code> on the original <code>int*</code>
|
||||
that has been passed to the constructor, even though <code>p2</code> itself is of type
|
||||
<code>shared_ptr<void></code> and stores a pointer of type <code>void*</code>.</p>
|
||||
|
||||
<p>Every <code>shared_ptr</code> meets the <code>CopyConstructible</code>, <code>MoveConstructible</code>,
|
||||
<code>CopyAssignable</code> and <code>MoveAssignable</code>
|
||||
requirements of the C++ Standard Library, and can be used in standard
|
||||
library containers. Comparison operators are supplied so that <code>shared_ptr</code>
|
||||
works with the standard library's associative containers.</p>
|
||||
<p>Because the implementation uses reference counting, cycles of <code>shared_ptr</code> instances
|
||||
will not be reclaimed. For example, if <code>main()</code> holds a <code>shared_ptr</code> to
|
||||
<code>A</code>, which directly or indirectly holds a <code>shared_ptr</code> back to <code>A</code>,
|
||||
<code>A</code>'s use count will be 2. Destruction of the original <code>shared_ptr</code> will
|
||||
leave <code>A</code> dangling with a use count of 1. Use <a href="weak_ptr.htm">weak_ptr</a>
|
||||
to "break cycles."</p>
|
||||
<p>The class template is parameterized on <code>T</code>, the type of the object pointed
|
||||
to. <code>shared_ptr</code> and most of its member functions place no
|
||||
requirements on <code>T</code>; it is allowed to be an incomplete type, or
|
||||
<code>void</code>. Member functions that do place additional requirements
|
||||
(<a href="#pointer_constructor">constructors</a>, <a href="#reset">reset</a>) are explicitly
|
||||
documented below.</p>
|
||||
<p><code>shared_ptr<T></code> can be implicitly converted to <code>shared_ptr<U></code>
|
||||
whenever <code>T*</code> can be implicitly converted to <code>U*</code>.
|
||||
In particular, <code>shared_ptr<T></code> is implicitly convertible
|
||||
to <code>shared_ptr<T const></code>, to <code>shared_ptr<U></code>
|
||||
where <code>U</code> is an accessible base of <code>T</code>, and to <code>
|
||||
shared_ptr<void></code>.</p>
|
||||
<p><code>shared_ptr</code> is now part of the C++11 Standard, as <code>std::shared_ptr</code>.</p>
|
||||
<p>Starting with Boost release 1.53, <code>shared_ptr</code> can be used to hold a pointer to a dynamically
|
||||
allocated array. This is accomplished by using an array type (<code>T[]</code> or <code>T[N]</code>) as
|
||||
the template parameter. There is almost no difference between using an unsized array, <code>T[]</code>,
|
||||
and a sized array, <code>T[N]</code>; the latter just enables <code>operator[]</code> to perform a range check
|
||||
on the index.</p>
|
||||
<blockquote><em>Example:</em><br><pre>shared_ptr<double[1024]> p1( new double[1024] );
|
||||
shared_ptr<double[]> p2( new double[n] );
|
||||
</pre></blockquote>
|
||||
|
||||
<h2 id="BestPractices">Best Practices</h2>
|
||||
<p>A simple guideline that nearly eliminates the possibility of memory leaks is:
|
||||
always use a named smart pointer variable to hold the result of <code>new</code>.
|
||||
Every occurence of the <code>new</code> keyword in the code should have the
|
||||
form:</p>
|
||||
<pre>shared_ptr<T> p(new Y);</pre>
|
||||
<p>It is, of course, acceptable to use another smart pointer in place of <code>shared_ptr</code>
|
||||
above; having <code>T</code> and <code>Y</code> be the same type, or
|
||||
passing arguments to <code>Y</code>'s constructor is also OK.</p>
|
||||
<p>If you observe this guideline, it naturally follows that you will have no
|
||||
explicit <code>delete</code> statements; <code>try/catch</code> constructs will
|
||||
be rare.</p>
|
||||
<p>Avoid using unnamed <code>shared_ptr</code> temporaries to save typing; to
|
||||
see why this is dangerous, consider this example:</p>
|
||||
<pre>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() );
|
||||
}
|
||||
</pre>
|
||||
<p>The function <code>ok</code> follows the guideline to the letter, whereas
|
||||
<code>bad</code> constructs the temporary <code>shared_ptr</code> in place,
|
||||
admitting the possibility of a memory leak. Since function arguments are
|
||||
evaluated in unspecified order, it is possible for <code>new int(2)</code> to
|
||||
be evaluated first, <code>g()</code> second, and we may never get to the
|
||||
<code>shared_ptr</code>constructor if <code>g</code> throws an exception.
|
||||
See <a href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</a> (also <a href="http://www.cuj.com/reference/articles/2002/0212/0212_sutter.htm">
|
||||
here</a>) of the issue for more information.</p>
|
||||
<p>The exception safety problem described above may also be eliminated by using
|
||||
the <a href="make_shared.html"><code>make_shared</code></a>
|
||||
or <a href="make_shared.html"><code>allocate_shared</code></a>
|
||||
factory functions defined in <code>boost/make_shared.hpp</code>.
|
||||
These factory functions also provide an efficiency benefit by consolidating allocations.</p>
|
||||
<h2 id="Synopsis">Synopsis</h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
class bad_weak_ptr: public std::exception;
|
||||
|
||||
template<class T> class <a href="weak_ptr.htm" >weak_ptr</a>;
|
||||
|
||||
template<class T> class shared_ptr {
|
||||
|
||||
public:
|
||||
|
||||
typedef <em>see below</em> <a href="#element_type" >element_type</a>;
|
||||
|
||||
<a href="#default_constructor" >shared_ptr</a>(); // never throws
|
||||
<a href="#default_constructor" >shared_ptr</a>(std::nullptr_t); // never throws
|
||||
|
||||
template<class Y> explicit <a href="#pointer_constructor" >shared_ptr</a>(Y * p);
|
||||
template<class Y, class D> <a href="#deleter_constructor" >shared_ptr</a>(Y * p, D d);
|
||||
template<class Y, class D, class A> <a href="#deleter_constructor" >shared_ptr</a>(Y * p, D d, A a);
|
||||
template<class D> <a href="#deleter_constructor" >shared_ptr</a>(std::nullptr_t p, D d);
|
||||
template<class D, class A> <a href="#deleter_constructor" >shared_ptr</a>(std::nullptr_t p, D d, A a);
|
||||
|
||||
<a href="#destructor" >~shared_ptr</a>(); // never throws
|
||||
|
||||
<a href="#copy_constructor" >shared_ptr</a>(shared_ptr const & r); // never throws
|
||||
template<class Y> <a href="#copy_constructor" >shared_ptr</a>(shared_ptr<Y> const & r); // never throws
|
||||
|
||||
<a href="#move_constructor" >shared_ptr</a>(shared_ptr && r); // never throws
|
||||
template<class Y> <a href="#move_constructor" >shared_ptr</a>(shared_ptr<Y> && r); // never throws
|
||||
|
||||
template<class Y> <a href="#aliasing_constructor" >shared_ptr</a>(shared_ptr<Y> const & r, element_type * p); // never throws
|
||||
|
||||
template<class Y> <a href="#aliasing_move_constructor" >shared_ptr</a>(shared_ptr<Y> && r, element_type * p); // never throws
|
||||
|
||||
template<class Y> explicit <a href="#weak_ptr_constructor" >shared_ptr</a>(<a href="weak_ptr.htm" >weak_ptr</a><Y> const & r);
|
||||
|
||||
template<class Y> explicit <a href="#auto_ptr_constructor" >shared_ptr</a>(std::auto_ptr<Y> & r);
|
||||
template<class Y> <a href="#auto_ptr_constructor" >shared_ptr</a>(std::auto_ptr<Y> && r);
|
||||
|
||||
template<class Y, class D> <a href="#unique_ptr_constructor" >shared_ptr</a>(std::unique_ptr<Y, D> && r);
|
||||
|
||||
shared_ptr & <a href="#assignment" >operator=</a>(shared_ptr const & r); // never throws
|
||||
template<class Y> shared_ptr & <a href="#assignment" >operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
|
||||
shared_ptr & <a href="#assignment" >operator=</a>(shared_ptr const && r); // never throws
|
||||
template<class Y> shared_ptr & <a href="#assignment" >operator=</a>(shared_ptr<Y> const && r); // never throws
|
||||
|
||||
template<class Y> shared_ptr & <a href="#assignment" >operator=</a>(std::auto_ptr<Y> & r);
|
||||
template<class Y> shared_ptr & <a href="#assignment" >operator=</a>(std::auto_ptr<Y> && r);
|
||||
|
||||
template<class Y, class D> shared_ptr & <a href="#assignment" >operator=</a>(std::unique_ptr<Y, D> && r);
|
||||
|
||||
shared_ptr & <a href="#assignment" >operator=</a>(std::nullptr_t); // never throws
|
||||
|
||||
void <a href="#reset" >reset</a>(); // never throws
|
||||
|
||||
template<class Y> void <a href="#reset" >reset</a>(Y * p);
|
||||
template<class Y, class D> void <a href="#reset" >reset</a>(Y * p, D d);
|
||||
template<class Y, class D, class A> void <a href="#reset" >reset</a>(Y * p, D d, A a);
|
||||
|
||||
template<class Y> void <a href="#reset" >reset</a>(shared_ptr<Y> const & r, element_type * p); // never throws
|
||||
|
||||
T & <a href="#indirection" >operator*</a>() const; // never throws; only valid when T is not an array type
|
||||
T * <a href="#indirection" >operator-></a>() const; // never throws; only valid when T is not an array type
|
||||
|
||||
element_type & <a href="#indirection" >operator[]</a>(std::ptrdiff_t i) const; // never throws; only valid when T is an array type
|
||||
|
||||
element_type * <a href="#get" >get</a>() const; // never throws
|
||||
|
||||
bool <a href="#unique" >unique</a>() const; // never throws
|
||||
long <a href="#use_count" >use_count</a>() const; // never throws
|
||||
|
||||
explicit <a href="#conversions" >operator bool</a>() const; // never throws
|
||||
|
||||
void <a href="#swap" >swap</a>(shared_ptr & b); // never throws
|
||||
|
||||
template<class Y> bool <a href="#owner_before" >owner_before</a>(shared_ptr<Y> const & rhs) const; // never throws
|
||||
template<class Y> bool <a href="#owner_before" >owner_before</a>(weak_ptr<Y> const & rhs) const; // never throws
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool <a href="#comparison" >operator==</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
bool <a href="#comparison" >operator!=</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
bool <a href="#comparison" >operator<</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator==</a>(shared_ptr<T> const & p, std::nullptr_t); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator==</a>(std::nullptr_t, shared_ptr<T> const & p); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator!=</a>(shared_ptr<T> const & p, std::nullptr_t); // never throws
|
||||
|
||||
template<class T>
|
||||
bool <a href="#comparison" >operator!=</a>(std::nullptr_t, shared_ptr<T> const & p); // never throws
|
||||
|
||||
template<class T> void <a href="#free-swap" >swap</a>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||
|
||||
template<class T> typename shared_ptr<T>::element_type * <a href="#get_pointer" >get_pointer</a>(shared_ptr<T> const & p); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
shared_ptr<T> <a href="#static_pointer_cast" >static_pointer_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
shared_ptr<T> <a href="#const_pointer_cast" >const_pointer_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
shared_ptr<T> <a href="#dynamic_pointer_cast" >dynamic_pointer_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
|
||||
template<class T, class U>
|
||||
shared_ptr<T> <a href="#reinterpret_pointer_cast" >reinterpret_pointer_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
|
||||
template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> & <a href="#insertion-operator" >operator<<</a> (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
|
||||
|
||||
template<class D, class T>
|
||||
D * <a href="#get_deleter">get_deleter</a>(shared_ptr<T> const & p);
|
||||
}</pre>
|
||||
<h2 id="Members">Members</h2>
|
||||
<h3 id="element_type">element_type</h3>
|
||||
<pre>typedef <em>...</em> element_type;</pre>
|
||||
<blockquote>
|
||||
<p><code>element_type</code> is <code>T</code> when <code>T</code> is not an array type,
|
||||
and <code>U</code> when <code>T</code> is <code>U[]</code> or <code>U[N]</code>.</p>
|
||||
</blockquote>
|
||||
<h3 id="default_constructor">default constructor</h3>
|
||||
<pre>shared_ptr(); // never throws
|
||||
shared_ptr(std::nullptr_t); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Constructs an <em>empty</em> <code>shared_ptr</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 0 && get() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<p><em>[The nothrow guarantee is important, since <code>reset()</code> is specified
|
||||
in terms of the default constructor; this implies that the constructor must not
|
||||
allocate memory.]</em></p>
|
||||
<h3 id="pointer_constructor">pointer constructor</h3>
|
||||
<pre>template<class Y> explicit shared_ptr(Y * p);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b>
|
||||
<code>Y</code> must be a complete type.
|
||||
The expression <code>delete[] p</code>, when <code>T</code> is an array type, or <code>delete p</code>,
|
||||
when <code>T</code> is not an array type,
|
||||
must be well-formed, must not invoke undefined behavior, and must not throw exceptions.
|
||||
When <code>T</code> is <code>U[N]</code>, <code>Y (*) [N]</code> must be convertible to <code>T*</code>;
|
||||
when <code>T</code> is <code>U[]</code>, <code>Y (*) []</code> must be convertible to <code>T*</code>;
|
||||
otherwise, <code>Y*</code> must be convertible to <code>T*</code>.
|
||||
</p>
|
||||
<p><b>Effects:</b>
|
||||
When <code>T</code> is not an array type, constructs a <code>shared_ptr</code> that <em>owns</em>
|
||||
the pointer <code>p</code>.
|
||||
Otherwise, constructs a <code>shared_ptr</code> that <em>owns</em>
|
||||
<code>p</code> and a deleter of an unspecified type that calls <code>delete[] p</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 1 && get() == p</code>.
|
||||
If <code>T</code> is not an array type and <code>p</code> is unambiguously convertible to <code>
|
||||
<a href="enable_shared_from_this.html">enable_shared_from_this</a><V>*</code>
|
||||
for some <code>V</code>, <code>p->shared_from_this()</code> returns a copy of
|
||||
<code>*this</code>.</p>
|
||||
<p><b>Throws:</b> <code>std::bad_alloc</code>, or an implementation-defined
|
||||
exception when a resource other than memory could not be obtained.</p>
|
||||
<p><b>Exception safety:</b> If an exception is thrown, the constructor calls
|
||||
<code>delete[] p</code>, when <code>T</code> is an array type,
|
||||
or <code>delete p</code>, when <code>T</code> is not an array type.</p>
|
||||
<p><b>Notes:</b> <code>p</code> must be a pointer to an object that was
|
||||
allocated via a C++ <code>new</code> expression or be 0. The postcondition that <a href="#use_count">
|
||||
use count</a> is 1 holds even if <code>p</code> is 0; invoking <code>delete</code>
|
||||
on a pointer that has a value of 0 is harmless.</p>
|
||||
</blockquote>
|
||||
<p><em>[This constructor is a template in order to remember the actual
|
||||
pointer type passed. The destructor will call <code>delete</code> with the
|
||||
same pointer, complete with its original type, even when <code>T</code> does
|
||||
not have a virtual destructor, or is <code>void</code>.]</em></p>
|
||||
<h3 id="deleter_constructor">constructors taking a deleter</h3>
|
||||
<pre>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);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b>
|
||||
<code>D</code> must be <code>CopyConstructible</code>. The copy constructor and destructor
|
||||
of <code>D</code> must not throw. The expression <code>d(p)</code> must be
|
||||
well-formed, must not invoke undefined behavior, and must not throw exceptions.
|
||||
<code>A</code> must be an <em>Allocator</em>, as described in section 20.1.5
|
||||
(<code>Allocator requirements</code>) of the C++ Standard.
|
||||
When <code>T</code> is <code>U[N]</code>, <code>Y (*) [N]</code> must be convertible to <code>T*</code>;
|
||||
when <code>T</code> is <code>U[]</code>, <code>Y (*) []</code> must be convertible to <code>T*</code>;
|
||||
otherwise, <code>Y*</code> must be convertible to <code>T*</code>.
|
||||
</p>
|
||||
<p><b>Effects:</b> Constructs a <code>shared_ptr</code> that <em>owns</em> the pointer <code>
|
||||
p</code> and the deleter <code>d</code>. The constructors taking an allocator <code>a</code>
|
||||
allocate memory using a copy of <code>a</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 1 && get() == p</code>.
|
||||
If <code>T</code> is not an array type and <code>p</code> is unambiguously convertible to <code>
|
||||
<a href="enable_shared_from_this.html">enable_shared_from_this</a><V>*</code>
|
||||
for some <code>V</code>, <code>p->shared_from_this()</code> returns a copy of
|
||||
<code>*this</code>.</p>
|
||||
<p><b>Throws:</b> <code>std::bad_alloc</code>, or an implementation-defined
|
||||
exception when a resource other than memory could not be obtained.</p>
|
||||
<p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p>
|
||||
<p><b>Notes:</b> When the the time comes to delete the object pointed to by <code>p</code>,
|
||||
the stored copy of <code>d</code> is invoked with the stored copy of <code>p</code>
|
||||
as an argument.</p>
|
||||
</blockquote>
|
||||
<p><em>[Custom deallocators allow a factory function returning a <code>shared_ptr</code>
|
||||
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 <code>shared_ptr</code>
|
||||
to a statically allocated object, and other variations allow a <code>shared_ptr</code>
|
||||
to be used as a wrapper for another smart pointer, easing interoperability.</em></p>
|
||||
<p><em>The support for custom deallocators does not impose significant overhead. Other <code>
|
||||
shared_ptr</code> features still require a deallocator to be kept.</em></p>
|
||||
<p><em>The requirement that the copy constructor of <code>D</code> does not throw comes from
|
||||
the pass by value. If the copy constructor throws, the pointer would leak.]</em></p>
|
||||
<h3 id="copy_constructor">copy and converting constructors</h3>
|
||||
<pre>shared_ptr(shared_ptr const & r); // never throws
|
||||
template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> <code>Y*</code> should be convertible to <code>T*</code>.</p>
|
||||
<p><b>Effects:</b> If <code>r</code> is <em>empty</em>, constructs an <em>empty</em> <code>shared_ptr</code>;
|
||||
otherwise, constructs a <code>shared_ptr</code> that <em>shares ownership</em> with <code>r</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>get() == r.get() && use_count() ==
|
||||
r.use_count()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="move_constructor">move constructors</h3>
|
||||
<pre>shared_ptr(shared_ptr && r); // never throws
|
||||
template<class Y> shared_ptr(shared_ptr<Y> && r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> <code>Y*</code> should be convertible to <code>T*</code>.</p>
|
||||
<p><b>Effects:</b> Move-constructs a <code>shared_ptr</code> from <code>r</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>*this</code> contains the old value of <code>r</code>. <code>r</code> is <em>empty</em> and <code>r.get() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="aliasing_constructor">aliasing constructor</h3>
|
||||
<pre>template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> constructs a <code>shared_ptr</code> that <em>shares ownership</em> with
|
||||
<code>r</code> and stores <code>p</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>get() == p && use_count() == r.use_count()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="aliasing_move_constructor">aliasing move constructor</h3>
|
||||
<pre>template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p); // never throws</pre>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Effects:</b> Move-constructs a <code>shared_ptr</code> from <code>r</code>, while
|
||||
storing <code>p</code> instead.
|
||||
</p>
|
||||
<p><b>Postconditions:</b> <code>get() == p</code> and <code>use_count()</code> equals the old count of <code>r</code>. <code>r</code> is <em>empty</em> and <code>r.get() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="weak_ptr_constructor">weak_ptr constructor</h3>
|
||||
<pre>template<class Y> explicit shared_ptr(<a href="weak_ptr.htm" >weak_ptr</a><Y> const & r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> <code>Y*</code> should be convertible to <code>T*</code>.</p>
|
||||
<p><b>Effects:</b> Constructs a <code>shared_ptr</code> that <em>shares ownership</em> with
|
||||
<code>r</code> and stores a copy of the pointer stored in <code>r</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
|
||||
<p><b>Throws:</b> <code>bad_weak_ptr</code> when <code>r.use_count() == 0</code>.</p>
|
||||
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
|
||||
effect.</p>
|
||||
</blockquote>
|
||||
<h3 id="auto_ptr_constructor">auto_ptr constructors</h3>
|
||||
<pre>template<class Y> shared_ptr(std::auto_ptr<Y> & r);
|
||||
template<class Y> shared_ptr(std::auto_ptr<Y> && r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> <code>Y*</code> should be convertible to <code>T*</code>.</p>
|
||||
<p><b>Effects:</b> Constructs a <code>shared_ptr</code>, as if by storing a copy of <code>r.release()</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 1</code>.</p>
|
||||
<p><b>Throws:</b> <code>std::bad_alloc</code>, or an implementation-defined
|
||||
exception when a resource other than memory could not be obtained.</p>
|
||||
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
|
||||
effect.</p>
|
||||
</blockquote>
|
||||
<h3 id="unique_ptr_constructor">unique_ptr constructor</h3>
|
||||
<pre>template<class Y, class D> shared_ptr(std::unique_ptr<Y, D> && r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> <code>Y*</code> should be convertible to <code>T*</code>.</p>
|
||||
<p><b>Effects:</b>
|
||||
Equivalent to <code>shared_ptr(r.release(), r.get_deleter())</code> when <code>D</code> is not a reference type.
|
||||
Otherwise, equivalent to <code>shared_ptr(r.release(), <em>del</em>)</code>, where <em>del</em> is a deleter
|
||||
that stores the reference <code>rd</code> returned from <code>r.get_deleter()</code> and <code>del(p)</code> calls <code>rd(p)</code>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 1</code>.</p>
|
||||
<p><b>Throws:</b> <code>std::bad_alloc</code>, or an implementation-defined
|
||||
exception when a resource other than memory could not be obtained.</p>
|
||||
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
|
||||
effect.</p>
|
||||
</blockquote>
|
||||
<h3 id="destructor">destructor</h3>
|
||||
<pre>~shared_ptr(); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b></p>
|
||||
<ul>
|
||||
<li>
|
||||
If <code>*this</code> is <em>empty</em>, or <em>shares ownership</em> with
|
||||
another <code>shared_ptr</code> instance (<code>use_count() > 1</code>),
|
||||
there are no side effects.</li>
|
||||
<li>
|
||||
Otherwise, if <code>*this</code> <em>owns</em> a pointer <code>p</code>
|
||||
and a deleter <code>d</code>, <code>d(p)</code>
|
||||
is called.</li>
|
||||
<li>
|
||||
Otherwise, <code>*this</code> <em>owns</em> a pointer <code>p</code>,
|
||||
and <code>delete p</code> is called.</li>
|
||||
</ul>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="assignment">assignment</h3>
|
||||
<pre>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);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</p>
|
||||
<p><b>Returns:</b> <code>*this</code>.</p>
|
||||
<p><b>Notes:</b> 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:</p>
|
||||
<pre>shared_ptr<int> p(new int);
|
||||
shared_ptr<void> q(p);
|
||||
p = p;
|
||||
q = p;
|
||||
</pre>
|
||||
<p>both assignments may be no-ops.</p>
|
||||
</blockquote>
|
||||
<pre>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);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr(std::move(r)).swap(*this)</code>.</p>
|
||||
<p><b>Returns:</b> <code>*this</code>.</p>
|
||||
</blockquote>
|
||||
<pre>shared_ptr & operator=(std::nullptr_t); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr().swap(*this)</code>.</p>
|
||||
<p><b>Returns:</b> <code>*this</code>.</p>
|
||||
</blockquote>
|
||||
<h3 id="reset">reset</h3>
|
||||
<pre>void reset(); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr().swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template<class Y> void reset(Y * p);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template<class Y, class D> void reset(Y * p, D d);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template<class Y, class D, class A> void reset(Y * p, D d, A a);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr(p, d, a).swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<pre>template<class Y> void reset(shared_ptr<Y> const & r, element_type * p); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>shared_ptr(r, p).swap(*this)</code>.</p>
|
||||
</blockquote>
|
||||
<h3 id="indirection">indirection</h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <code>T</code> should not be an array type. The stored pointer must not be 0.</p>
|
||||
<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <code>T</code> should not be an array type. The stored pointer must not be 0.</p>
|
||||
<p><b>Returns:</b> the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>element_type & operator[](std::ptrdiff_t i) const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requirements:</b> <code>T</code> should be an array type. The stored pointer must not be 0.
|
||||
<code>i >= 0</code>. If <code>T</code> is <code>U[N]</code>, <code>i < N</code>.</p>
|
||||
<p><b>Returns:</b> <code>get()[i]</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="get">get</h3>
|
||||
<pre>element_type * get() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the stored pointer.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="unique">unique</h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> <code>unique()</code> may be faster than <code>use_count()</code>.
|
||||
If you are using <code>unique()</code> to implement copy on write, do not rely
|
||||
on a specific value when the stored pointer is zero.</p>
|
||||
</blockquote>
|
||||
<h3 id="use_count">use_count</h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> the number of <code>shared_ptr</code> objects, <code>*this</code> included,
|
||||
that <i>share ownership</i> with <code>*this</code>, or 0 when <code>*this</code>
|
||||
is <em>empty</em>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> <code>use_count()</code> is not necessarily efficient. Use only
|
||||
for debugging and testing purposes, not for production code.</p>
|
||||
</blockquote>
|
||||
<h3 id="conversions">conversions</h3>
|
||||
<pre>explicit operator bool() const; // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>get() != 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> This conversion operator allows <code>shared_ptr</code> objects to be
|
||||
used in boolean contexts, like <code>if(p && p->valid()) {}</code>.</p>
|
||||
</blockquote>
|
||||
<p><em>[The conversion to bool is not merely syntactic sugar. It allows <code>shared_ptr</code>s
|
||||
to be declared in conditions when using <a href="#dynamic_pointer_cast">dynamic_pointer_cast</a>
|
||||
or <a href="weak_ptr.htm#lock">weak_ptr::lock</a>.]</em></p>
|
||||
<h3 id="swap">swap</h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="owner_before">swap</h3>
|
||||
<pre>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</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> See the description of <a href="#comparison"><code>operator<</code></a>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h2 id="functions">Free Functions</h2>
|
||||
<h3 id="comparison">comparison</h3>
|
||||
<pre>template<class T, class U>
|
||||
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>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</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>p.get() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>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</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>p.get() != 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>template<class T, class U>
|
||||
bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> an unspecified value such that</p>
|
||||
<ul>
|
||||
<li>
|
||||
<code>operator<</code> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
||||
of the C++ standard;</li>
|
||||
<li>
|
||||
under the equivalence relation defined by <code>operator<</code>, <code>!(a
|
||||
< b) && !(b < a)</code>, two <code>shared_ptr</code> instances
|
||||
are equivalent if and only if they <em>share ownership</em> or are both <em>empty</em>.</li></ul>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> Allows <code>shared_ptr</code> objects to be used as keys in
|
||||
associative containers.</p>
|
||||
</blockquote>
|
||||
<p><em>[<code>Operator<</code> has been preferred over a <code>std::less</code>
|
||||
specialization for consistency and legality reasons, as <code>std::less</code>
|
||||
is required to return the results of <code>operator<</code>, and many
|
||||
standard algorithms use <code>operator<</code> instead of <code>std::less</code>
|
||||
for comparisons when a predicate is not supplied. Composite objects, like <code>std::pair</code>,
|
||||
also implement their <code>operator<</code> in terms of their contained
|
||||
subobjects' <code>operator<</code>.</em></p>
|
||||
<p><em>The rest of the comparison operators are omitted by design.]</em></p>
|
||||
<h3 id="free-swap">swap</h3>
|
||||
<pre>template<class T>
|
||||
void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Equivalent to <code>a.swap(b)</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> Matches the interface of <code>std::swap</code>. Provided as an aid to
|
||||
generic programming.</p>
|
||||
</blockquote>
|
||||
<p><em>[<code>swap</code> is defined in the same namespace as <code>shared_ptr</code>
|
||||
as this is currently the only legal way to supply a <code>swap</code> function
|
||||
that has a chance to be used by the standard library.]</em></p>
|
||||
<h3 id="get_pointer">get_pointer</h3>
|
||||
<pre>template<class T>
|
||||
typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>p.get()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> Provided as an aid to generic programming. Used by <a href="../bind/mem_fn.html">
|
||||
mem_fn</a>.</p>
|
||||
</blockquote>
|
||||
<h3 id="static_pointer_cast">static_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>static_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b> <code>shared_ptr<T>( r, static_cast<typename shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<p><b>Notes:</b> the seemingly equivalent expression
|
||||
<code>shared_ptr<T>(static_cast<T*>(r.get()))</code>
|
||||
will eventually result in undefined behavior, attempting to delete the same
|
||||
object twice.</p>
|
||||
</blockquote>
|
||||
<h3 id="const_pointer_cast">const_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>const_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b> <code>shared_ptr<T>( r, const_cast<typename shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="dynamic_pointer_cast">dynamic_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>dynamic_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b></p>
|
||||
<ul>
|
||||
<li>
|
||||
When <code>dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())</code> returns a nonzero value <code>p</code>,
|
||||
<code>shared_ptr<T>(r, p)</code>;</li>
|
||||
<li>
|
||||
Otherwise, <code>shared_ptr<T>()</code>.</li></ul>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="reinterpret_pointer_cast">reinterpret_pointer_cast</h3>
|
||||
<pre>template<class T, class U>
|
||||
shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> The expression <code>reinterpret_cast<T*>( (U*)0 )</code>
|
||||
must be well-formed.</p>
|
||||
<p><b>Returns:</b> <code>shared_ptr<T>( r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()) )</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3 id="insertion-operator">operator<<</h3>
|
||||
<pre>template<class E, class T, class Y>
|
||||
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> <code>os << p.get();</code>.</p>
|
||||
<p><b>Returns:</b> <code>os</code>.</p>
|
||||
</blockquote>
|
||||
<h3 id="get_deleter">get_deleter</h3>
|
||||
<pre>template<class D, class T>
|
||||
D * get_deleter(shared_ptr<T> const & p);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> If <code>*this</code> <em>owns</em> a deleter <code>d</code>
|
||||
of type (cv-unqualified) <code>D</code>, returns <code>&d</code>;
|
||||
otherwise returns 0.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h2 id="example">Example</h2>
|
||||
<p>See <a href="example/shared_ptr_example.cpp">shared_ptr_example.cpp</a> for a
|
||||
complete example program. The program builds a <code>std::vector</code> and <code>std::set</code>
|
||||
of <code>shared_ptr</code> objects.</p>
|
||||
<p>Note that after the containers have been populated, some of the <code>shared_ptr</code>
|
||||
objects will have a use count of 1 rather than a use count of 2, since the set
|
||||
is a <code>std::set</code> rather than a <code>std::multiset</code>, and thus does not
|
||||
contain duplicate entries. Furthermore, the use count may be even higher at
|
||||
various times while <code>push_back</code> and <code>insert</code> 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.</p>
|
||||
<h2 id="HandleBody">Handle/Body Idiom</h2>
|
||||
<p>One common usage of <code>shared_ptr</code> is to implement a handle/body (also called
|
||||
pimpl) idiom which avoids exposing the body (implementation) in the header
|
||||
file.</p>
|
||||
<p>The <a href="example/shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</a>
|
||||
sample program includes a header file, <a href="example/shared_ptr_example2.hpp">shared_ptr_example2.hpp</a>,
|
||||
which uses a <code>shared_ptr</code> to an incomplete type to hide the
|
||||
implementation. The instantiation of member functions which require a complete
|
||||
type occurs in the <a href="example/shared_ptr_example2.cpp">shared_ptr_example2.cpp</a>
|
||||
implementation file. Note that there is no need for an explicit destructor.
|
||||
Unlike <code>~scoped_ptr</code>, <code>~shared_ptr</code> does not require that <code>T</code> be a complete
|
||||
type.</p>
|
||||
<h2 id="ThreadSafety">Thread Safety</h2>
|
||||
<p><code>shared_ptr</code> objects offer the same level of thread safety as
|
||||
built-in types. A <code>shared_ptr</code> instance can be "read" (accessed
|
||||
using only const operations) simultaneously by multiple threads. Different <code>shared_ptr</code>
|
||||
instances can be "written to" (accessed using mutable operations such as <code>operator=
|
||||
</code>or <code>reset</code>) simultaneously by multiple threads (even
|
||||
when these instances are copies, and share the same reference count
|
||||
underneath.)</p>
|
||||
<p>Any other simultaneous accesses result in undefined behavior.</p>
|
||||
<p>Examples:</p>
|
||||
<pre>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
|
||||
</pre>
|
||||
<p> </p>
|
||||
<p>Starting with Boost release 1.33.0, <code>shared_ptr</code> uses a lock-free
|
||||
implementation on most common platforms.</p>
|
||||
<p>If your program is single-threaded and does not link to any libraries that might
|
||||
have used <code>shared_ptr</code> in its default configuration, you can <code>
|
||||
#define</code> the macro <code>BOOST_SP_DISABLE_THREADS</code> on a
|
||||
project-wide basis to switch to ordinary non-atomic reference count updates.</p>
|
||||
<p>(Defining <code>BOOST_SP_DISABLE_THREADS</code> 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.)</p>
|
||||
<p>You can define the macro <code>BOOST_SP_USE_PTHREADS</code> to turn off the
|
||||
lock-free platform-specific implementation and fall back to the generic
|
||||
<code>pthread_mutex_t</code>-based code.</p>
|
||||
<h2 id="FAQ">Frequently Asked Questions</h2>
|
||||
<p><b>Q.</b> 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?</p>
|
||||
<p>
|
||||
<b>A.</b> An important goal of <code>shared_ptr</code> 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.)
|
||||
</p>
|
||||
<p><b>Q.</b> Why doesn't <code>shared_ptr</code> have template parameters supplying
|
||||
traits or policies to allow extensive user customization?</p>
|
||||
<p>
|
||||
<b>A.</b> Parameterization discourages users. The <code>shared_ptr</code> 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, <code>shared_ptr</code> is the smart
|
||||
pointer of choice for a wide range of applications. (Those interested in policy
|
||||
based smart pointers should read <a href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201704315&rl=1">
|
||||
Modern C++ Design</a> by Andrei Alexandrescu.)
|
||||
</p>
|
||||
<p><b>Q.</b> I am not convinced. Default parameters can be used where appropriate
|
||||
to hide the complexity. Again, why not policies?</p>
|
||||
<p>
|
||||
<b>A.</b> Template parameters affect the type. See the answer to the first
|
||||
question above.
|
||||
</p>
|
||||
<p><b>Q.</b> Why doesn't <code>shared_ptr</code> use a linked list implementation?</p>
|
||||
<p>
|
||||
<b>A.</b> A linked list implementation does not offer enough advantages to
|
||||
offset the added cost of an extra pointer. See <a href="smarttests.htm">timings</a>
|
||||
page. In addition, it is expensive to make a linked list implementation thread
|
||||
safe.
|
||||
</p>
|
||||
<p><b>Q.</b> Why doesn't <code>shared_ptr</code> (or any of the other Boost smart
|
||||
pointers) supply an automatic conversion to <code>T*</code>?</p>
|
||||
<p>
|
||||
<b>A.</b> Automatic conversion is believed to be too error prone.
|
||||
</p>
|
||||
<p><b>Q.</b> Why does <code>shared_ptr</code> supply <code>use_count()</code>?</p>
|
||||
<p>
|
||||
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
|
||||
progenitors had <code>use_count()</code>, and it was useful in tracking down bugs in a
|
||||
complex project that turned out to have cyclic-dependencies.
|
||||
</p>
|
||||
<p><b>Q.</b> Why doesn't <code>shared_ptr</code> specify complexity requirements?</p>
|
||||
<p>
|
||||
<b>A.</b> Because complexity requirements limit implementors and complicate the
|
||||
specification without apparent benefit to <code>shared_ptr</code> users. For example,
|
||||
error-checking implementations might become non-conforming if they had to meet
|
||||
stringent complexity requirements.
|
||||
</p>
|
||||
<p><b>Q.</b> Why doesn't <code>shared_ptr</code> provide a <code>release()</code> function?</p>
|
||||
<p>
|
||||
<b>A.</b> <code>shared_ptr</code> cannot give away ownership unless it's <code>unique()</code>
|
||||
because the other copy will still destroy the object.</p>
|
||||
<p>Consider:</p>
|
||||
<blockquote><pre>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.</pre>
|
||||
</blockquote>
|
||||
<p>Furthermore, the pointer returned by <code>release()</code> would be difficult
|
||||
to deallocate reliably, as the source <code>shared_ptr</code> could have been created
|
||||
with a custom deleter.
|
||||
</p>
|
||||
<p><b>Q.</b> Why is <code>operator->()</code> const, but its return value is a
|
||||
non-const pointer to the element type?</p>
|
||||
<p>
|
||||
<b>A.</b> 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. <code>shared_ptr</code> is "as close to raw pointers as possible
|
||||
but no closer".
|
||||
</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>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 <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a>
|
||||
or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>.</small></p>
|
||||
</body>
|
||||
</html>
|
224
smart_ptr.htm
224
smart_ptr.htm
@ -1,224 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Smart Pointers</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">Smart Pointers</h1>
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#common_requirements">Common Requirements</a><br>
|
||||
<a href="#Exception_Safety">Exception Safety</a><br>
|
||||
<a href="#Exception-specifications">Exception-specifications</a><br>
|
||||
<a href="#History">History and Acknowledgements</a><br>
|
||||
<a href="#References">References</a></p>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>The smart pointer library provides six smart pointer class templates:</p>
|
||||
<div align="left">
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td>
|
||||
<td><a href="../../boost/scoped_ptr.hpp"><boost/scoped_ptr.hpp></a></td>
|
||||
<td>Simple sole ownership of single objects. Noncopyable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
|
||||
<td><a href="../../boost/scoped_array.hpp"><boost/scoped_array.hpp></a></td>
|
||||
<td>Simple sole ownership of arrays. Noncopyable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
|
||||
<td><a href="../../boost/shared_ptr.hpp"><boost/shared_ptr.hpp></a></td>
|
||||
<td>Object ownership shared among multiple pointers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="shared_array.htm"><b>shared_array</b></a></td>
|
||||
<td><a href="../../boost/shared_array.hpp"><boost/shared_array.hpp></a></td>
|
||||
<td>Array ownership shared among multiple pointers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="weak_ptr.htm"><b>weak_ptr</b></a></td>
|
||||
<td><a href="../../boost/weak_ptr.hpp"><boost/weak_ptr.hpp></a></td>
|
||||
<td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="intrusive_ptr.html"><b>intrusive_ptr</b></a></td>
|
||||
<td><a href="../../boost/intrusive_ptr.hpp"><boost/intrusive_ptr.hpp></a></td>
|
||||
<td>Shared ownership of objects with an embedded reference count.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
|
||||
<p>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.</p>
|
||||
<p>Additionally, the smart pointer library provides efficient factory functions
|
||||
for creating smart pointer objects:</p>
|
||||
<div align="left">
|
||||
<table border="1" cellpadding="4" cellspacing="0">
|
||||
<tr>
|
||||
<td><a href="make_shared.html"><b>make_shared, allocate_shared</b></a> for objects</td>
|
||||
<td><a href="../../boost/make_shared.hpp"><boost/make_shared.hpp></a></td>
|
||||
<td>Efficient creation of <code>shared_ptr</code> objects.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="make_shared_array.html"><b>make_shared, allocate_shared</b></a> for arrays</td>
|
||||
<td><a href="../../boost/make_shared.hpp"><boost/make_shared.hpp></a></td>
|
||||
<td>Efficient creation of <code>shared_ptr</code> arrays.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="make_unique.html"><b>make_unique</b></a></td>
|
||||
<td><a href="../../boost/make_unique.hpp"><boost/make_unique.hpp></a></td>
|
||||
<td>Creation of <code>unique_ptr</code> objects and arrays.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
|
||||
provided to verify correct operation.</p>
|
||||
<p>A page on <a href="compatibility.htm">compatibility</a> with older versions of
|
||||
the Boost smart pointer library describes some of the changes since earlier
|
||||
versions of the smart pointer implementation.</p>
|
||||
<p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of interest
|
||||
to those curious about performance issues.</p>
|
||||
<P>A page on <A href="sp_techniques.html">smart pointer programming techniques</A> lists
|
||||
some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P>
|
||||
<h2><a name="common_requirements">Common Requirements</a></h2>
|
||||
<p>These smart pointer class templates have a template parameter, <b>T</b>, 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 <b>operator delete</b>
|
||||
for objects of type <b>T</b> throw exceptions.</p>
|
||||
<p><b>T</b> may be an incomplete type at the point of smart pointer declaration.
|
||||
Unless otherwise specified, it is required that <b>T</b> 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 <a href="../utility/utility.htm#checked_delete">
|
||||
<b>checked_delete</b></a> function template.</p>
|
||||
<P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of
|
||||
its member functions do not require <STRONG>T</STRONG> to be a complete type.</P>
|
||||
<h3>Rationale</h3>
|
||||
<p>The requirements on <b>T</b> 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 <b>T</b> 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.</p>
|
||||
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at
|
||||
destruction time, but <b>shared_ptr</b> does not.</p>
|
||||
<h2><a name="Exception_Safety">Exception Safety</a></h2>
|
||||
<p>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 <b>T</b> meets
|
||||
the <a href="#common_requirements">common requirements</a>) is <b>std::bad_alloc</b>,
|
||||
and that is thrown only by functions which are explicitly documented as
|
||||
possibly throwing <b>std::bad_alloc</b>.</p>
|
||||
<h2><a name="Exception-specifications">Exception-specifications</a></h2>
|
||||
<p>Exception-specifications are not used; see <a href="http://www.boost.org/more/lib_guide.htm#Exception-specification">
|
||||
exception-specification rationale</a>.</p>
|
||||
<p>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: <code>
|
||||
// never throws</code>.
|
||||
</p>
|
||||
<p>Functions which destroy objects of the pointed to type are prohibited from
|
||||
throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p>
|
||||
<h2><a name="History">History</a> and Acknowledgements</h2>
|
||||
<p>February 2017. Glen Fernandes rewrote <b>allocate_shared</b>
|
||||
and <b>make_shared</b> for arrays for a more optimal and more
|
||||
maintainable implementation.</p>
|
||||
<p>February 2014. Glen Fernandes updated overloads of <b>make_shared</b> and
|
||||
<b>allocate_shared</b> to conform to the specification in C++ standard paper
|
||||
<a href="#D&F-14">[D&F-14]</a>, and implemented <b>make_unique</b> for
|
||||
arrays and objects. Peter Dimov and Glen Fernandes updated the scalar and
|
||||
array implementations, respectively, to resolve C++ standard library defect
|
||||
2070.</p>
|
||||
<p>November 2012. Glen Fernandes provided implementations of <b>make_shared</b>
|
||||
and <b>allocate_shared</b> 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 <a href="make_shared_array.html">make_shared and allocate_shared for
|
||||
arrays</a> page for more information.</p>
|
||||
<p>January 2002. Peter Dimov reworked all four classes, adding features, fixing
|
||||
bugs, and splitting them into four separate headers, and added <b>weak_ptr</b>.
|
||||
See the <a href="compatibility.htm">compatibility</a> page for a summary of the
|
||||
changes.</p>
|
||||
<p>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.</p>
|
||||
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
|
||||
and <b>std::less</b> specializations for shared types.</p>
|
||||
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p>
|
||||
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a
|
||||
number of suggestions resulting in numerous improvements.</p>
|
||||
<p>October 1998. Beman Dawes proposed reviving the original semantics under the
|
||||
names <b>safe_ptr</b> and <b>counted_ptr</b>, 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 <b>std::auto_ptr</b> interface, and various function signatures and
|
||||
semantics were finalized.</p>
|
||||
<p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
|
||||
and discussed on the <a href="http://www.boost.org">boost.org</a> 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:
|
||||
<ul>
|
||||
<li>
|
||||
Direct detached: the shared_ptr contains a pointer to the object, and a pointer
|
||||
to the count.
|
||||
<li>
|
||||
Indirect detached: the shared_ptr contains a pointer to a helper object, which
|
||||
in turn contains a pointer to the object and the count.
|
||||
<li>
|
||||
Embedded attached: the count is a member of the object pointed to.
|
||||
<li>
|
||||
Placement attached: the count is attached via operator new manipulations.</li>
|
||||
</ul>
|
||||
<p>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.</p>
|
||||
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage
|
||||
users", and in the end we choose to supply only the direct implementation.</p>
|
||||
<p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b>
|
||||
and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b>
|
||||
and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few
|
||||
cases where the Library Working Group's recommendations were not followed by
|
||||
the full committee, <b>counted_ptr</b> was rejected and surprising
|
||||
transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
|
||||
<h2><a name="References">References</a></h2>
|
||||
<p>[<a name="D&F-14">D&F-14</a>] Peter Dimov & Glen Fernandes, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html">
|
||||
Extending make_shared to Support Arrays, Revision 1</a>, C++ committee document N3870,
|
||||
January, 2014.</p>
|
||||
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf">
|
||||
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555,
|
||||
July, 1994.</p>
|
||||
<p>[<a name="E&D-94">E&D-94</a>] John R. Ellis & David L. Detlefs, <a href="http://www.usenix.org/publications/library/proceedings/c++94/full_papers/ellis.a">
|
||||
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings,
|
||||
February, 1994. This paper includes an extensive discussion of weak pointers
|
||||
and an extensive bibliography.</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
Distributed under the Boost Software License, Version 1.0. See accompanying
|
||||
file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at
|
||||
<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
BIN
smarttest.zip
BIN
smarttest.zip
Binary file not shown.
542
smarttests.htm
542
smarttests.htm
@ -1,542 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Smart Pointer Timings</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle" border="0">Smart Pointer Timings</h1>
|
||||
|
||||
<p>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.</p>
|
||||
<p>Thanks are due to <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>,
|
||||
Gavin Collings,
|
||||
<a href="http://www.boost.org/people/greg_colvin.htm">Greg Colvin</a> and
|
||||
<a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a>
|
||||
for test code and trial implementations, the final version of which can be found
|
||||
in .zip format <a href="smarttest.zip">here</a>.</p>
|
||||
<h2>Description</h2>
|
||||
<p>Two tests were run: the first aimed to obtain timings for two basic individual
|
||||
operations:</p>
|
||||
<ol type="i">
|
||||
<li> Initial construction from raw pointer.</li>
|
||||
<li> An amortized copy operation consisting of half an assignment and half a
|
||||
copy construction - designed to reflect average usage.</li>
|
||||
</ol>
|
||||
<p>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.</p>
|
||||
<p>Five smart pointer implementation strategies were tested:</p>
|
||||
<ol type="i">
|
||||
<li>Counted pointer using a heap allocated reference count, this is referred
|
||||
to as <b>simple counted</b>.</li>
|
||||
<li>Counted pointer using a special purpose allocator for the reference count
|
||||
- <b>special counted</b>.</li>
|
||||
<li>Counted pointer using an intrusive reference count - <b>intrusive</b>.</li>
|
||||
<li>Linked pointer as described above - <b>linked</b>.</li>
|
||||
<li>Cyclic pointer, a counted implementation using a std::deque for allocation
|
||||
with provision for weak pointers and garbage collection of cycles of pointers
|
||||
- <b>cyclic</b>.</li>
|
||||
</ol>
|
||||
<p>on two compilers:</p>
|
||||
<ol type="i">
|
||||
<li>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).</li>
|
||||
<li>gcc 2.95.2 using full optimization (-O3 -DNDEBUG).</li>
|
||||
</ol>
|
||||
<p>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.</p>
|
||||
<p>All tests were run on a PII-200 running Windows NT version 4.0</p>
|
||||
<h2> </h2>
|
||||
<h2>Operation Timing Test Results</h2>
|
||||
<p>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.</p>
|
||||
<table border="0" align="center">
|
||||
<tr>
|
||||
<td width="20" height="20"> </td>
|
||||
<td> </td>
|
||||
<td width="20"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20"> </td>
|
||||
<td><img src="msvcspeed.gif" width="560" height="355" alt="MSVC speed graph"></td>
|
||||
<td width="20"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="20"> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><img src="gccspeed.gif" width="560" height="355" alt="GCC speed graph"></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="20"> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<p>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) : -</p>
|
||||
<p> </p>
|
||||
<h4 align="center">MSVC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="400">
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">
|
||||
<div align="center">initialization</div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">copy operation</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">3000 +/- 170</td>
|
||||
<td class="codetablecell" align="center">104 +/- 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1330 +/- 50</td>
|
||||
<td class="codetablecell" align="center">85 +/- 9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1000 +/- 20</td>
|
||||
<td class="codetablecell" align="center">71 +/- 3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">970 +/- 60</td>
|
||||
<td class="codetablecell" align="center">136 +/- 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">1290 +/- 70</td>
|
||||
<td class="codetablecell" align="center">112 +/- 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">dumb</th>
|
||||
<td class="codetablecell" align="center">1020 +/- 20</td>
|
||||
<td class="codetablecell" align="center">10 +/- 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1038 +/- 30</td>
|
||||
<td class="codetablecell" align="center">10 +/- 5</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h4 align="center"> </h4>
|
||||
<h4 align="center">GCC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="400">
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">
|
||||
<div align="center">initialization</div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">copy operation</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">4620 +/- 150</td>
|
||||
<td class="codetablecell" align="center">301 +/- 28</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1990 +/- 40</td>
|
||||
<td class="codetablecell" align="center">264 +/- 7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1590 +/- 70</td>
|
||||
<td class="codetablecell" align="center">181 +/- 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">1470 +/- 140</td>
|
||||
<td class="codetablecell" align="center">345 +/- 26</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">2180 +/- 100</td>
|
||||
<td class="codetablecell" align="center">330 +/- 18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">dumb</th>
|
||||
<td class="codetablecell" align="center">1590 +/- 70</td>
|
||||
<td class="codetablecell" align="center">74 +/- 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1430 +/- 60</td>
|
||||
<td class="codetablecell" align="center">27 +/- 11</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>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.</p>
|
||||
<h3>Detail</h3>
|
||||
<p>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.</p>
|
||||
<h2> </h2>
|
||||
<h2>Container Test Results</h2>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p> All times are in seconds for 300,000 contained pointers.</p>
|
||||
<h4 align="center">GCC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="500">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th class="codetabletop" colspan="2">vector</th>
|
||||
<th class="codetabletop" colspan="2">list</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">
|
||||
<div align="center">fill</div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
<th class="codetabletop2" width="80">fill</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">46.54</td>
|
||||
<td class="codetablecell" align="center">2.44</td>
|
||||
<td class="codetablecell" align="center">47.09</td>
|
||||
<td class="codetablecell" align="center">3.22</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">14.02</td>
|
||||
<td class="codetablecell" align="center">2.83</td>
|
||||
<td class="codetablecell" align="center">7.28</td>
|
||||
<td class="codetablecell" align="center">3.21</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">12.15</td>
|
||||
<td class="codetablecell" align="center">1.91</td>
|
||||
<td class="codetablecell" align="center">7.99</td>
|
||||
<td class="codetablecell" align="center">3.08</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">12.46</td>
|
||||
<td class="codetablecell" align="center">2.32</td>
|
||||
<td class="codetablecell" align="center">8.14</td>
|
||||
<td class="codetablecell" align="center">3.27</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">22.60</td>
|
||||
<td class="codetablecell" align="center">3.19</td>
|
||||
<td class="codetablecell" align="center">1.63</td>
|
||||
<td class="codetablecell" align="center">3.18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">11.81</td>
|
||||
<td class="codetablecell" align="center">0.24</td>
|
||||
<td class="codetablecell" align="center">27.51</td>
|
||||
<td class="codetablecell" align="center">0.77</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<h4 align="center">MSVC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="500">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th class="codetabletop" colspan="2">vector</th>
|
||||
<th class="codetabletop" colspan="2">list</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">
|
||||
<div align="center">fill</div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
<th class="codetabletop2" width="80">fill</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1.83</td>
|
||||
<td class="codetablecell" align="center">2.37</td>
|
||||
<td class="codetablecell" align="center">1.86</td>
|
||||
<td class="codetablecell" align="center">4.85</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1.04</td>
|
||||
<td class="codetablecell" align="center">2.35</td>
|
||||
<td class="codetablecell" align="center">1.38</td>
|
||||
<td class="codetablecell" align="center">4.58</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1.04</td>
|
||||
<td class="codetablecell" align="center">1.84</td>
|
||||
<td class="codetablecell" align="center">1.16</td>
|
||||
<td class="codetablecell" align="center">4.29</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">1.08</td>
|
||||
<td class="codetablecell" align="center">2.00</td>
|
||||
<td class="codetablecell" align="center">1.21</td>
|
||||
<td class="codetablecell" align="center">4.33</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">1.38</td>
|
||||
<td class="codetablecell" align="center">2.84</td>
|
||||
<td class="codetablecell" align="center">1.47</td>
|
||||
<td class="codetablecell" align="center">4.73</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">0.67</td>
|
||||
<td class="codetablecell" align="center">0.28</td>
|
||||
<td class="codetablecell" align="center">1.24</td>
|
||||
<td class="codetablecell" align="center">1.81</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<h2>Code Size</h2>
|
||||
<p>The following code sizes were determined by inspection of generated code for
|
||||
MSVC only. Sizes are given in the form N / M / I where:</p>
|
||||
<ul type="circle">
|
||||
<li> N is the instruction count of the operation</li>
|
||||
<li>M is the size of the code in bytes</li>
|
||||
<li>I determines whether generated code was inlined or not I = inline, O = "outline"</li>
|
||||
</ul>
|
||||
<p> </p>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="570">
|
||||
<tr>
|
||||
<th height="28" width="140">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="80">
|
||||
<div align="center">ptr()</div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="80">ptr(p)</th>
|
||||
<th height="28" class="codetabletop" width="80">ptr(ptr)</th>
|
||||
<th height="28" class="codetabletop" width="80">op=()</th>
|
||||
<th height="28" class="codetabletop" width="80">
|
||||
<div align="center">~ptr()</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">38/110/O</td>
|
||||
<td class="codetablecell" align="center">38/110/O</td>
|
||||
<td class="codetablecell" align="center">9/23/I</td>
|
||||
<td class="codetablecell" align="center">22/57/I</td>
|
||||
<td class="codetablecell" align="center">17/40/I</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center"><font size="-1">50/141/O</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">50/141/O</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">9/23/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">23/64/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">13/38/I</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center"><font size="-1">1/2/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">3/6/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">3/6/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">6/11/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">6/11/I</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">linked</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center"><font size="-1">5/19/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">5/15/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">10/30/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">27/59/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">14/38/I</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>During the code inspection, a couple of minor points were noticed: -</p>
|
||||
<ul>
|
||||
<li>Function inlining was critical to performance.</li>
|
||||
<li>For MSVC, at least, a "delete 0" caused execution of 11 assembly
|
||||
instructions, including a function call. So in cases where performance is
|
||||
at an absolute premium it can be worth inserting the extra manual test.</li>
|
||||
</ul>
|
||||
<h2> </h2>
|
||||
<h2>Data Size</h2>
|
||||
<p>The following smart pointer sizes were obtained in bytes</p>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="270">
|
||||
<tr>
|
||||
<th height="28" width="150">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="60">
|
||||
<div align="center">MSVC</div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="60">
|
||||
<div align="center">GCC</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">12</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">4</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">4</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">linked</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">12</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">12</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">cyclic</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2> </h2>
|
||||
<h2>Summary</h2>
|
||||
<p>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: -</p>
|
||||
<ul>
|
||||
<li>Deterministic individual, as opposed to amortized, operation time. This
|
||||
weighs against any implementation depending on an allocator.</li>
|
||||
<li>Multithreaded synchronization. This weighs against an implementation which
|
||||
spreads its information as in the case of linked pointer.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p>© 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.</p>
|
||||
</body>
|
||||
</html>
|
@ -1,765 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Smart Pointer Programming Techniques</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">Smart Pointer Programming Techniques</h1>
|
||||
<p><A href="#incomplete">Using incomplete classes for implementation hiding</A><br>
|
||||
<A href="#pimpl">The "Pimpl" idiom</A><br>
|
||||
<A href="#abstract">Using abstract classes for implementation hiding</A><br>
|
||||
<A href="#preventing_delete">Preventing <code>delete px.get()</code></A><br>
|
||||
<A href="#array">Using a <code>shared_ptr</code> to hold a pointer to an array</A><br>
|
||||
<A href="#encapsulation">Encapsulating allocation details, wrapping factory
|
||||
functions</A><br>
|
||||
<A href="#static">Using a <code>shared_ptr</code> to hold a pointer to a statically
|
||||
allocated object</A><br>
|
||||
<A href="#com">Using a <code>shared_ptr</code> to hold a pointer to a COM object</A><br>
|
||||
<A href="#intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
|
||||
with an embedded reference count</A><br>
|
||||
<A href="#another_sp">Using a <code>shared_ptr</code> to hold another shared
|
||||
ownership smart pointer</A><br>
|
||||
<A href="#from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A><br>
|
||||
<A href="#in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
|
||||
to <code>this</code> in a constructor</A><br>
|
||||
<A href="#from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A><br>
|
||||
<A href="#handle">Using <code>shared_ptr</code> as a smart counted handle</A><br>
|
||||
<A href="#on_block_exit">Using <code>shared_ptr</code> to execute code on block
|
||||
exit</A><br>
|
||||
<A href="#pvoid">Using <code>shared_ptr<void></code> to hold an arbitrary
|
||||
object</A><br>
|
||||
<A href="#extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
|
||||
instances</A><br>
|
||||
<A href="#as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A><br>
|
||||
<A href="#wrapper">Using <code>shared_ptr</code> to wrap member function calls</A><br>
|
||||
<A href="#delayed">Delayed deallocation</A><br>
|
||||
<A href="#weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A><br>
|
||||
</p>
|
||||
<h2><A name="incomplete">Using incomplete classes for implementation hiding</A></h2>
|
||||
<p>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:</p>
|
||||
<pre>class FILE;
|
||||
|
||||
FILE * fopen(char const * name, char const * mode);
|
||||
void fread(FILE * f, void * data, size_t size);
|
||||
void fclose(FILE * f);
|
||||
</pre>
|
||||
<p>It is possible to express the above interface using <code>shared_ptr</code>,
|
||||
eliminating the need to manually call <code>fclose</code>:</p>
|
||||
<pre>class FILE;
|
||||
|
||||
shared_ptr<FILE> fopen(char const * name, char const * mode);
|
||||
void fread(shared_ptr<FILE> f, void * data, size_t size);
|
||||
</pre>
|
||||
<p>This technique relies on <code>shared_ptr</code>'s ability to execute a custom
|
||||
deleter, eliminating the explicit call to <code>fclose</code>, and on the fact
|
||||
that <code>shared_ptr<X></code> can be copied and destroyed when <code>X</code>
|
||||
is incomplete.</p>
|
||||
<h2><A name="pimpl">The "Pimpl" idiom</A></h2>
|
||||
<p>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. <code>shared_ptr</code> can be used to implement a "Pimpl":</p>
|
||||
<pre>// 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);
|
||||
};
|
||||
</pre>
|
||||
<pre>// 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);
|
||||
}
|
||||
</pre>
|
||||
<p>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, <code>
|
||||
file</code> is <code>CopyConstructible</code> and <code>Assignable</code>,
|
||||
allowing its use in standard containers.</p>
|
||||
<h2><A name="abstract">Using abstract classes for implementation hiding</A></h2>
|
||||
<p>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, <code>shared_ptr</code> can be used as the return type of
|
||||
the factory functions:</p>
|
||||
<pre>// X.hpp:
|
||||
|
||||
class X
|
||||
{
|
||||
public:
|
||||
|
||||
virtual void f() = 0;
|
||||
virtual void g() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
~X() {}
|
||||
};
|
||||
|
||||
shared_ptr<X> createX();
|
||||
</pre>
|
||||
<pre>-- 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;
|
||||
}
|
||||
</pre>
|
||||
<p>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 <code>X</code>;
|
||||
the <code>shared_ptr<X></code> instance returned from <code>createX</code>
|
||||
will correctly call <code>~X_impl</code>.</p>
|
||||
<h2><A name="preventing_delete">Preventing <code>delete px.get()</code></A></h2>
|
||||
<p>It is often desirable to prevent client code from deleting a pointer that is
|
||||
being managed by <code>shared_ptr</code>. The previous technique showed one
|
||||
possible approach, using a protected destructor. Another alternative is to use
|
||||
a private deleter:</p>
|
||||
<pre>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;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<h2><A name="array">Using a <code>shared_ptr</code> to hold a pointer to an array</A></h2>
|
||||
<p>A <code>shared_ptr</code> can be used to hold a pointer to an array allocated
|
||||
with <code>new[]</code>:</p>
|
||||
<pre>shared_ptr<X> px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A><X>());
|
||||
</pre>
|
||||
<p>Note, however, that <code><A href="shared_array.htm">shared_array</A></code> is
|
||||
often preferable, if this is an option. It has an array-specific interface,
|
||||
without <code>operator*</code> and <code>operator-></code>, and does not
|
||||
allow pointer conversions.</p>
|
||||
<h2><A name="encapsulation">Encapsulating allocation details, wrapping factory
|
||||
functions</A></h2>
|
||||
<p><code>shared_ptr</code> 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 <code>CreateX</code> might allocate <code>X</code> from its own private
|
||||
heap, <code>~X</code> may be inaccessible, or <code>X</code> may be incomplete:</p>
|
||||
<pre>X * CreateX();
|
||||
void DestroyX(X *);
|
||||
</pre>
|
||||
<p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is
|
||||
to call <code>DestroyX</code>.</p>
|
||||
<P>Here is how a <code>shared_ptr</code>-based wrapper may look like:</P>
|
||||
<pre>shared_ptr<X> createX()
|
||||
{
|
||||
shared_ptr<X> px(CreateX(), DestroyX);
|
||||
return px;
|
||||
}
|
||||
</pre>
|
||||
<p>Client code that calls <code>createX</code> still does not need to know how the
|
||||
object has been allocated, but now the destruction is automatic.</p>
|
||||
<h2><A name="static">Using a <code>shared_ptr</code> to hold a pointer to a statically
|
||||
allocated object</A></h2>
|
||||
<p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already
|
||||
existing object, so that the <code>shared_ptr</code> does not attempt to
|
||||
destroy the object when there are no more references left. As an example, the
|
||||
factory function:</p>
|
||||
<pre>shared_ptr<X> createX();
|
||||
</pre>
|
||||
<p>in certain situations may need to return a pointer to a statically allocated <code>X</code>
|
||||
instance.</p>
|
||||
<P>The solution is to use a custom deleter that does nothing:</P>
|
||||
<pre>struct null_deleter
|
||||
{
|
||||
void operator()(void const *) const
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static X x;
|
||||
|
||||
shared_ptr<X> createX()
|
||||
{
|
||||
shared_ptr<X> px(&x, null_deleter());
|
||||
return px;
|
||||
}
|
||||
</pre>
|
||||
<p>The same technique works for any object known to outlive the pointer.</p>
|
||||
<h2><A name="com">Using a <code>shared_ptr</code> to hold a pointer to a COM Object</A></h2>
|
||||
<p>Background: COM objects have an embedded reference count and two member
|
||||
functions that manipulate it. <code>AddRef()</code> increments the count. <code>Release()</code>
|
||||
decrements the count and destroys itself when the count drops to zero.</p>
|
||||
<P>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</P>
|
||||
<pre>shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
|
||||
{
|
||||
p->AddRef();
|
||||
shared_ptr<IWhatever> pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&IWhatever::Release));
|
||||
return pw;
|
||||
}
|
||||
</pre>
|
||||
<p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will
|
||||
not "register" in the embedded count of the COM object; they will share the
|
||||
single reference created in <code>make_shared_from_COM</code>. Weak pointers
|
||||
created from <code>pw</code> will be invalidated when the last <code>shared_ptr</code>
|
||||
is destroyed, regardless of whether the COM object itself is still alive.</p>
|
||||
<P>As <A href="../bind/mem_fn.html#Q3">explained</A> in the <code>mem_fn</code> documentation,
|
||||
you need to <A href="../bind/mem_fn.html#stdcall">#define
|
||||
BOOST_MEM_FN_ENABLE_STDCALL</A> first.</P>
|
||||
<h2><A name="intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
|
||||
with an embedded reference count</A></h2>
|
||||
<p>This is a generalization of the above technique. The example assumes that the
|
||||
object implements the two functions required by <code><A href="intrusive_ptr.html">intrusive_ptr</A></code>,
|
||||
<code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p>
|
||||
<pre>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;
|
||||
}
|
||||
</pre>
|
||||
<h2><A name="another_sp">Using a <code>shared_ptr</code> to hold another shared
|
||||
ownership smart pointer</A></h2>
|
||||
<p>One of the design goals of <code>shared_ptr</code> is to be used in library
|
||||
interfaces. It is possible to encounter a situation where a library takes a <code>shared_ptr</code>
|
||||
argument, but the object at hand is being managed by a different reference
|
||||
counted or linked smart pointer.</p>
|
||||
<P>It is possible to exploit <code>shared_ptr</code>'s custom deleter feature to
|
||||
wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</P>
|
||||
<pre>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;
|
||||
}
|
||||
</pre>
|
||||
<p>One subtle point is that deleters are not allowed to throw exceptions, and the
|
||||
above example as written assumes that <code>p_.reset()</code> doesn't throw. If
|
||||
this is not the case, <code>p_.reset()</code> should be wrapped in a <code>try {}
|
||||
catch(...) {}</code> block that ignores exceptions. In the (usually
|
||||
unlikely) event when an exception is thrown and ignored, <code>p_</code> will
|
||||
be released when the lifetime of the deleter ends. This happens when all
|
||||
references, including weak pointers, are destroyed or reset.</p>
|
||||
<P>Another twist is that it is possible, given the above <code>shared_ptr</code> instance,
|
||||
to recover the original smart pointer, using <code><A href="shared_ptr.htm#get_deleter">
|
||||
get_deleter</A></code>:</P>
|
||||
<pre>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
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<h2><A name="from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A></h2>
|
||||
<p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw
|
||||
pointer to an object that is already managed by another <code>shared_ptr</code>
|
||||
instance. Example:</p>
|
||||
<pre>void f(X * p)
|
||||
{
|
||||
shared_ptr<X> px(<i>???</i>);
|
||||
}
|
||||
</pre>
|
||||
<p>Inside <code>f</code>, we'd like to create a <code>shared_ptr</code> to <code>*p</code>.</p>
|
||||
<P>In the general case, this problem has no solution. One approach is to modify <code>f</code>
|
||||
to take a <code>shared_ptr</code>, if possible:</P>
|
||||
<pre>void f(shared_ptr<X> px);
|
||||
</pre>
|
||||
<p>The same transformation can be used for nonvirtual member functions, to convert
|
||||
the implicit <code>this</code>:</p>
|
||||
<pre>void X::f(int m);
|
||||
</pre>
|
||||
<p>would become a free function with a <code>shared_ptr</code> first argument:</p>
|
||||
<pre>void f(shared_ptr<X> this_, int m);
|
||||
</pre>
|
||||
<p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting,
|
||||
use <code><A href="#intrusive">make_shared_from_intrusive</A></code> described
|
||||
above. Or, if it's known that the <code>shared_ptr</code> created in <code>f</code>
|
||||
will never outlive the object, use <A href="#static">a null deleter</A>.</p>
|
||||
<h2><A name="in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
|
||||
to <code>this</code> in a constructor</A></h2>
|
||||
<p>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:</p>
|
||||
<pre>class X
|
||||
{
|
||||
public:
|
||||
|
||||
X()
|
||||
{
|
||||
shared_ptr<X> this_(<i>???</i>);
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<p>In the general case, the problem cannot be solved. The <code>X</code> instance
|
||||
being constructed can be an automatic variable or a static variable; it can be
|
||||
created on the heap:</p>
|
||||
<pre>shared_ptr<X> px(new X);</pre>
|
||||
<P>but at construction time, <code>px</code> does not exist yet, and it is
|
||||
impossible to create another <code>shared_ptr</code> instance that shares
|
||||
ownership with it.</P>
|
||||
<P>Depending on context, if the inner <code>shared_ptr</code> <code>this_</code> doesn't
|
||||
need to keep the object alive, use a <code>null_deleter</code> as explained <A href="#static">
|
||||
here</A> and <A href="#weak_without_shared">here</A>. If <code>X</code> is
|
||||
supposed to always live on the heap, and be managed by a <code>shared_ptr</code>,
|
||||
use a static factory function:</P>
|
||||
<pre>class X
|
||||
{
|
||||
private:
|
||||
|
||||
X() { ... }
|
||||
|
||||
public:
|
||||
|
||||
static shared_ptr<X> create()
|
||||
{
|
||||
shared_ptr<X> px(new X);
|
||||
// use px as 'this_'
|
||||
return px;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<h2><A name="from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A></h2>
|
||||
<p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code>
|
||||
in a virtual member function under the assumption that <code>this</code> is
|
||||
already managed by a <code>shared_ptr</code>. The transformations <A href="#from_raw">
|
||||
described in the previous technique</A> cannot be applied.</p>
|
||||
<P>A typical example:</P>
|
||||
<pre>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(<i>???</i>);
|
||||
return px;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p>
|
||||
<pre>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;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<p>The library now includes a helper class template <code><A href="enable_shared_from_this.html">
|
||||
enable_shared_from_this</A></code> that can be used to encapsulate the
|
||||
solution:</p>
|
||||
<pre>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();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member
|
||||
in <code><A href="enable_shared_from_this.html">enable_shared_from_this</A></code>.
|
||||
Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p>
|
||||
<h2><A name="handle">Using <code>shared_ptr</code> as a smart counted handle</A></h2>
|
||||
<p>Some library interfaces use opaque handles, a variation of the <A href="#incomplete">
|
||||
incomplete class technique</A> described above. An example:</p>
|
||||
<pre>typedef void * HANDLE;
|
||||
HANDLE CreateProcess();
|
||||
void CloseHandle(HANDLE);
|
||||
</pre>
|
||||
<p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the
|
||||
handle and get reference counting and automatic resource management for free:</p>
|
||||
<pre>typedef shared_ptr<void> handle;
|
||||
|
||||
handle createProcess()
|
||||
{
|
||||
shared_ptr<void> pv(CreateProcess(), CloseHandle);
|
||||
return pv;
|
||||
}
|
||||
</pre>
|
||||
<h2><A name="on_block_exit">Using <code>shared_ptr</code> to execute code on block exit</A></h2>
|
||||
<p><code>shared_ptr<void></code> can automatically execute cleanup code when
|
||||
control leaves a scope.</p>
|
||||
<UL>
|
||||
<LI>
|
||||
Executing <code>f(p)</code>, where <code>p</code> is a pointer:</LI></UL>
|
||||
<pre> shared_ptr<void> guard(p, f);
|
||||
</pre>
|
||||
<UL>
|
||||
<LI>
|
||||
Executing arbitrary code: <code>f(x, y)</code>:</LI></UL>
|
||||
<pre> shared_ptr<void> guard(static_cast<void*>(0), <A href="../bind/bind.html" >bind</A>(f, x, y));
|
||||
</pre>
|
||||
<P>For a more thorough treatment, see the article "Simplify Your Exception-Safe
|
||||
Code" by Andrei Alexandrescu and Petru Marginean, available online at <A href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts">
|
||||
http://www.cuj.com/experts/1812/alexandr.htm?topic=experts</A>.</P>
|
||||
<h2><A name="pvoid">Using <code>shared_ptr<void></code> to hold an arbitrary
|
||||
object</A></h2>
|
||||
<p><code>shared_ptr<void></code> can act as a generic object pointer similar
|
||||
to <code>void*</code>. When a <code>shared_ptr<void></code> instance
|
||||
constructed as:</p>
|
||||
<pre> shared_ptr<void> pv(new X);
|
||||
</pre>
|
||||
<p>is destroyed, it will correctly dispose of the <code>X</code> object by
|
||||
executing <code>~X</code>.</p>
|
||||
<p>This propery can be used in much the same manner as a raw <code>void*</code> is
|
||||
used to temporarily strip type information from an object pointer. A <code>shared_ptr<void></code>
|
||||
can later be cast back to the correct type by using <code><A href="shared_ptr.htm#static_pointer_cast">
|
||||
static_pointer_cast</A></code>.</p>
|
||||
<h2><A name="extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
|
||||
instances</A></h2>
|
||||
<p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator<</code>
|
||||
comparisons required by standard associative containers such as <code>std::map</code>.
|
||||
This can be used to non-intrusively associate arbitrary data with objects
|
||||
managed by <code>shared_ptr</code>:</p>
|
||||
<pre>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;
|
||||
</pre>
|
||||
<h2><A name="as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A></h2>
|
||||
<p>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 <code>shared_ptr</code>
|
||||
as a mutex lock:</p>
|
||||
<pre>class mutex
|
||||
{
|
||||
public:
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
shared_ptr<mutex> lock(mutex & m)
|
||||
{
|
||||
m.lock();
|
||||
return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
|
||||
}
|
||||
</pre>
|
||||
<p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be
|
||||
encapsulated in a dedicated <code>shared_lock</code> class:</p>
|
||||
<pre>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)) {}
|
||||
};
|
||||
</pre>
|
||||
<p><code>shared_lock</code> can now be used as:</p>
|
||||
<pre> shared_lock lock(m);
|
||||
</pre>
|
||||
<p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code>
|
||||
shared_ptr<void></code>'s ability to hide type information.</p>
|
||||
<h2><A name="wrapper">Using <code>shared_ptr</code> to wrap member function calls</A></h2>
|
||||
<p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap</code>/<code>CallProxy</code>
|
||||
scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function
|
||||
Calls" (available online at <A href="http://www.stroustrup.com/wrapper.pdf">http://www.stroustrup.com/wrapper.pdf</A>).
|
||||
An implementation is given below:</p>
|
||||
<pre>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_, <A href="../bind/mem_fn.html" >mem_fn</A>(&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();
|
||||
}
|
||||
</pre>
|
||||
<h2><A name="delayed">Delayed deallocation</A></h2>
|
||||
<p>In some situations, a single <code>px.reset()</code> can trigger an expensive
|
||||
deallocation in a performance-critical region:</p>
|
||||
<pre>class X; // ~X is expensive
|
||||
|
||||
class Y
|
||||
{
|
||||
shared_ptr<X> px;
|
||||
|
||||
public:
|
||||
|
||||
void f()
|
||||
{
|
||||
px.reset();
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<p>The solution is to postpone the potential deallocation by moving <code>px</code>
|
||||
to a dedicated free list that can be periodically emptied when performance and
|
||||
response times are not an issue:</p>
|
||||
<pre>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
|
||||
</pre>
|
||||
<p>Another variation is to move the free list logic to the construction point by
|
||||
using a delayed deleter:</p>
|
||||
<pre>struct delayed_deleter
|
||||
{
|
||||
template<class T> void operator()(T * p)
|
||||
{
|
||||
try
|
||||
{
|
||||
shared_ptr<void> pv(p);
|
||||
free_list.push_back(pv);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
}
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<h2><A name="weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A></h2>
|
||||
<p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p>
|
||||
<pre>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_; }
|
||||
};
|
||||
</pre>
|
||||
<p>When the object's lifetime ends, <code>X::this_</code> will be destroyed, and
|
||||
all weak pointers will automatically expire.</p>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>Copyright © 2003 Peter Dimov. Distributed under the Boost Software License, Version
|
||||
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
240
weak_ptr.htm
240
weak_ptr.htm
@ -1,240 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>weak_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
|
||||
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
|
||||
width="277" align="middle" border="0">weak_ptr class template</h1>
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Members">Members</A><br>
|
||||
<A href="#functions">Free Functions</A><br>
|
||||
<A href="#FAQ">Frequently Asked Questions</A>
|
||||
</p>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's
|
||||
already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG>
|
||||
can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors">
|
||||
the <STRONG>shared_ptr</STRONG> constructor</A> or the member function <STRONG><A href="#lock">
|
||||
lock</A></STRONG>. When the last <b>shared_ptr</b> to the object goes
|
||||
away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG>
|
||||
from the <b>weak_ptr</b> instances that refer to the deleted object will fail:
|
||||
the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>,
|
||||
and <STRONG>weak_ptr::lock</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p>
|
||||
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements
|
||||
of the C++ Standard Library, and so can be used in standard library containers.
|
||||
Comparison operators are supplied so that <b>weak_ptr</b> works with the
|
||||
standard library's associative containers.</p>
|
||||
<P><STRONG>weak_ptr</STRONG> operations never throw exceptions.</P>
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||
to.</p>
|
||||
<P>Compared to <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> 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 <b>weak_ptr</b>
|
||||
has a <b>get</b> member function that returns a raw pointer, and consider this
|
||||
innocent piece of code:</P>
|
||||
<pre>shared_ptr<int> p(new int(5));
|
||||
weak_ptr<int> q(p);
|
||||
|
||||
// some time later
|
||||
|
||||
if(int * r = q.get())
|
||||
{
|
||||
// use *r
|
||||
}
|
||||
</pre>
|
||||
<P>Imagine that after the <STRONG>if</STRONG>, but immediately before <STRONG>r</STRONG>
|
||||
is used, another thread executes the statement <code>p.reset()</code>. Now <STRONG>r</STRONG>
|
||||
is a dangling pointer.</P>
|
||||
<P>The solution to this problem is to create a temporary <STRONG>shared_ptr</STRONG>
|
||||
from <STRONG>q</STRONG>:</P>
|
||||
<pre>shared_ptr<int> p(new int(5));
|
||||
weak_ptr<int> q(p);
|
||||
|
||||
// some time later
|
||||
|
||||
if(shared_ptr<int> r = q.<A href="#lock" >lock</A>())
|
||||
{
|
||||
// use *r
|
||||
}
|
||||
</pre>
|
||||
<p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>.
|
||||
Even if <code>p.reset()</code> is executed in another thread, the object will
|
||||
stay alive until <STRONG>r</STRONG> goes out of scope or is reset. By obtaining
|
||||
a <STRONG>shared_ptr</STRONG> to the object, we have effectively locked it
|
||||
against destruction.</p>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
template<class T> class weak_ptr {
|
||||
|
||||
public:
|
||||
typedef T <A href="#element_type" >element_type</A>;
|
||||
|
||||
<A href="#default-constructor" >weak_ptr</A>();
|
||||
|
||||
template<class Y> <A href="#constructors" >weak_ptr</A>(shared_ptr<Y> const & r);
|
||||
<A href="#constructors" >weak_ptr</A>(weak_ptr const & r);
|
||||
template<class Y> <A href="#constructors" >weak_ptr</A>(weak_ptr<Y> const & r);
|
||||
|
||||
<A href="#destructor" >~weak_ptr</A>();
|
||||
|
||||
weak_ptr & <A href="#assignment" >operator=</A>(weak_ptr const & r);
|
||||
template<class Y> weak_ptr & <A href="#assignment" >operator=</A>(weak_ptr<Y> const & r);
|
||||
template<class Y> weak_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r);
|
||||
|
||||
long <A href="#use_count" >use_count</A>() const;
|
||||
bool <A href="#expired" >expired</A>() const;
|
||||
shared_ptr<T> <A href="#lock" >lock</A>() const;
|
||||
|
||||
void <A href="#reset" >reset</A>();
|
||||
void <A href="#swap" >swap</A>(weak_ptr<T> & b);
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool <A href="#comparison" >operator<</A>(weak_ptr<T> const & a, weak_ptr<U> const & b);
|
||||
|
||||
template<class T>
|
||||
void <A href="#free-swap" >swap</A>(weak_ptr<T> & a, weak_ptr<T> & b);
|
||||
}
|
||||
</pre>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<blockquote>
|
||||
<p>Provides the type of the template parameter T.</p>
|
||||
</blockquote>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre><a name="default-constructor">weak_ptr();</a></pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>weak_ptr</b>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<pre>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);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> If <STRONG>r</STRONG> is <EM>empty</EM>, constructs an <EM>empty</EM>
|
||||
<STRONG>weak_ptr</STRONG>; otherwise, constructs a <b>weak_ptr</b> that <EM>shares
|
||||
ownership</EM> with <STRONG>r</STRONG> as if by storing a copy of the
|
||||
pointer stored in <b>r</b>.</p>
|
||||
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
<pre>~weak_ptr();</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Destroys this <b>weak_ptr</b> but has no effect on the object
|
||||
its stored pointer points to.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="assignment">assignment</a></h3>
|
||||
<pre>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);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>weak_ptr(r).swap(*this)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied
|
||||
guarantees) via different means, without creating a temporary.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const;</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> 0 if <STRONG>*this</STRONG> is <EM>empty</EM>; otherwise, the
|
||||
number of <b>shared_ptr</b> objects that <EM>share ownership</EM> with <STRONG>*this</STRONG>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
|
||||
for debugging and testing purposes, not for production code.</P>
|
||||
</blockquote>
|
||||
<h3><a name="expired">expired</a></h3>
|
||||
<pre>bool expired() const;</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> <code>use_count() == 0</code>.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.</P>
|
||||
</blockquote>
|
||||
<h3><a name="lock">lock</a></h3>
|
||||
<pre>shared_ptr<T> lock() const;</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Returns:</B> <code>expired()? shared_ptr<T>(): shared_ptr<T>(*this)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset();</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(weak_ptr & b);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
</blockquote>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<class T, class U>
|
||||
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> an unspecified value such that</p>
|
||||
<UL>
|
||||
<LI>
|
||||
<b>operator<</b> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
||||
of the C++ standard;
|
||||
<LI>
|
||||
under the equivalence relation defined by <STRONG>operator<</STRONG>, <code>!(a
|
||||
< b) && !(b < a)</code>, two <STRONG>weak_ptr</STRONG> instances
|
||||
are equivalent if and only if they <EM>share ownership</EM> or are both <EM>empty</EM>.</LI></UL>
|
||||
<p><b>Throws:</b> nothing.</p>
|
||||
<P><B>Notes:</B> Allows <STRONG>weak_ptr</STRONG> objects to be used as keys in
|
||||
associative containers.</P>
|
||||
</blockquote>
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<class T>
|
||||
void swap(weak_ptr<T> & a, weak_ptr<T> & b)</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
|
||||
<P><B>Throws:</B> nothing.</P>
|
||||
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
||||
generic programming.</P>
|
||||
</BLOCKQUOTE>
|
||||
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
|
||||
<P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its
|
||||
constructor?</P>
|
||||
<P><b>A.</b> No. A <STRONG>weak_ptr</STRONG> can only be created from a <STRONG>shared_ptr</STRONG>,
|
||||
and at object construction time no <STRONG>shared_ptr</STRONG> to the object
|
||||
exists yet. Even if you could create a temporary <STRONG>shared_ptr</STRONG> to <STRONG>
|
||||
this</STRONG>, it would go out of scope at the end of the constructor, and
|
||||
all <STRONG>weak_ptr</STRONG> instances would instantly expire.</P>
|
||||
<P>The solution is to make the constructor private, and supply a factory function
|
||||
that returns a <STRONG>shared_ptr</STRONG>:<BR>
|
||||
</P>
|
||||
<pre>
|
||||
class X
|
||||
{
|
||||
private:
|
||||
|
||||
X();
|
||||
|
||||
public:
|
||||
|
||||
static shared_ptr<X> create()
|
||||
{
|
||||
shared_ptr<X> px(new X);
|
||||
// create weak pointers from px here
|
||||
return px;
|
||||
}
|
||||
};
|
||||
</pre>
|
||||
<hr>
|
||||
<p>$Date$</p>
|
||||
<p><small>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 <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
|
||||
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user