Revised to match the style of the C++ standard.

[SVN r12806]
This commit is contained in:
Peter Dimov
2002-02-14 17:12:07 +00:00
parent 6c5d296722
commit 309e6dd82e

View File

@ -1,376 +1,423 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head>
<title>shared_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_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="#example">Example</A><br>
<A href="#Handle/Body">Handle/Body Idiom</A><br>
<A href="#FAQ">Frequently Asked Questions</A><br>
<A href="smarttests.htm">Smart Pointer Timings</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>shared_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 when the last <b>shared_ptr</b>
pointing to it is destroyed or reset. See the <A href="#example">example</A>.</p>
<p>Every <b>shared_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>shared_ptr</b>
works with the standard library's associative containers.</p>
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically
allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for
that usage.</p>
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not
work correctly with cyclic data structures. For example, if <b>main()</b> holds
a <b>shared_ptr</b> to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b>
back to <b>A</b>, <b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
will leave <b>A</b> dangling with a use count of 1.</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>. <b>T</b> may be <b>void</b>, but in that case,
either an explicit delete function must be passed in, or the pointed-to object
must have a trivial destructor.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
<head> template&lt;typename T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>;
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>shared_ptr</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_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="#example">Example</a><br>
<a href="#Handle/Body">Handle/Body Idiom</a><br>
<a href="#FAQ">Frequently Asked Questions</a><br>
<a href="smarttests.htm">Smart Pointer Timings</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>shared_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 when
the last <b>shared_ptr</b> pointing to it is destroyed or reset.
See the <a href="#example">example</a>.</p>
<p>Every <b>shared_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>shared_ptr</b> works with
the standard library's associative containers.</p>
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a
dynamically allocated array. See <a href="shared_array.htm"><b>shared_array</b></a>
for that usage.</p>
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not work
correctly with cyclic data structures. For example, if <b>main()</b> holds a <b>shared_ptr</b>
to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
will leave <b>A</b> dangling with a use count of 1.</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>.
<b>T</b> may be <b>void</b>, but in that case, either an explicit delete
function must be passed in, or the pointed-to object must have a trivial destructor.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename T&gt; class shared_ptr { template&lt;typename T&gt; class shared_ptr {
public: public:
typedef T <a href="#element_type">element_type</a>; typedef T <A href="#element_type" >element_type</A>;
explicit <a href="#constructors">shared_ptr</a>(T * p = 0); explicit <A href="#constructors" >shared_ptr</A>(T * p = 0);
template&lt;typename D&gt; <a href="#constructors">shared_ptr</a>(T * p, D d); template&lt;typename D&gt; <A href="#constructors" >shared_ptr</A>(T * p, D d);
<a href="#destructor">~shared_ptr</a>(); // never throws <A href="#destructor" >~shared_ptr</A>(); // never throws
<a href="#constructors">shared_ptr</a>(shared_ptr const &amp; r); // never throws <A href="#constructors" >shared_ptr</A>(shared_ptr const &amp; r); // never throws
template&lt;typename Y&gt; <a href="#constructors">shared_ptr</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; <A href="#constructors" >shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; <a href="#constructors">shared_ptr</a>(std::auto_ptr&lt;Y&gt; &amp; r); <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A> const &amp; r);
template&lt;typename Y&gt; <A href="#constructors" >shared_ptr</A>(std::auto_ptr&lt;Y&gt; &amp; r);
shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr const &amp; r); // never throws shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;typename Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(std::auto_ptr&lt;Y&gt; &amp; r); template&lt;typename Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r);
void <a href="#reset">reset</a>(T * p = 0); void <A href="#reset" >reset</A>(T * p = 0);
template&lt;typename D&gt; void <a href="#reset">reset</a>(T * p, D d); template&lt;typename D&gt; void <A href="#reset" >reset</A>(T * p, D d);
T &amp; <a href="#indirection">operator*</a>() const; // never throws T &amp; <A href="#indirection" >operator*</A>() const; // never throws
T * <a href="#indirection">operator-&gt;</a>() const; // never throws T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
T * <a href="#get">get</a>() const; // never throws T * <A href="#get" >get</A>() const; // never throws
bool <a href="#unique">unique</a>() const; // never throws bool <A href="#unique" >unique</A>() const; // never throws
long <a href="#use_count">use_count</a>() const; // never throws long <A href="#use_count" >use_count</A>() const; // never throws
void <a href="#swap">swap</a>(shared_ptr&lt;T&gt; &amp; b); // never throws void <A href="#swap" >swap</A>(shared_ptr&lt;T&gt; &amp; b); // never throws
}; };
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#comparison">operator==</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws bool <A href="#comparison" >operator==</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
bool <a href="#comparison">operator!=</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws bool <A href="#comparison" >operator!=</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;typename T&gt; template&lt;typename T&gt;
bool <a href="#comparison">operator&lt;</a>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws bool <A href="#comparison" >operator&lt;</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;typename T&gt; void <a href="#free-swap">swap</a>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws template&lt;typename T&gt; void <A href="#free-swap" >swap</A>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr&lt;U&gt; const &amp; r); // never throws shared_ptr&lt;T&gt; <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr&lt;U&gt; const &amp; r); shared_ptr&lt;T&gt; <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr&lt;U&gt; const &amp; r);
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_polymorphic_cast">shared_polymorphic_cast</a>(shared_ptr&lt;U&gt; const &amp; r); shared_ptr&lt;T&gt; <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr&lt;U&gt; const &amp; r);
template&lt;typename T, typename U&gt; template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt <a href="#shared_polymorphic_downcast">shared_polymorphic_downcast</a>(shared_ptr&lt;U&gt; const &amp; r); // never throws shared_ptr&lt;T&gt; <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
}</pre> }</pre>
<h2><a name="Members">Members</a></h2>
<h2><a name="Members">Members</a></h2> <h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<h3><a name="element_type">element_type</a></h3> <blockquote>
<pre>typedef T element_type;</pre> <p>Provides the type of the template parameter T.</p>
<p>Provides the type of the stored pointer.</p> </blockquote>
<h3><a name="constructors">constructors</a></h3>
<h3><a name="constructors">constructors</a></h3> <pre>explicit shared_ptr(T * p = 0);</pre>
<blockquote>
<pre>explicit shared_ptr(T * p = 0);</pre> <p><b>Requirements:</b> The expression <code>delete p</code> must be well-formed
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>, which and must not invoke undefined behavior.
must be a pointer to an object that was allocated via a C++ <b>new</b> expression or be 0. </p>
Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">~shared_ptr</a>). <p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>.</p>
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>. <p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p>
If an exception is thrown, <b>delete p</b> is called.</p> <p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is
<pre>template&lt;typename D&gt; shared_ptr(T * p, D d);</pre> called.</p>
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and of <b>d</b>. <P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was
Afterwards, the <a href="#use_count">use count</a> is 1. allocated via a C++ <B>new</B> expression or be 0. The postcondition that <A href="#use_count">
<b>D</b>'s copy constructor and destructor must not throw. use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG>
When the the time comes to delete the object pointed to by <b>p</b>, the object on a pointer that has a value of 0 is harmless.</P>
<b>d</b> is used in the statement <b>d(p)</b>. Invoking the object <b>d</b> with </blockquote>
parameter <b>p</b> in this way must not throw. <pre>template&lt;typename D&gt; shared_ptr(T * p, D d);</pre>
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>. <blockquote>
If an exception is thrown, <b>d(p)</b> is called.</p> <p><b>Requirements:</b> The copy constructor and destructor of <b>D</b> must not
throw. The expression <code>d(p)</code> must be well-formed, must not invoke
<pre>shared_ptr(shared_ptr const &amp; r); // never throws undefined behavior, and must not throw exceptions.
template&lt;typename Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws </p>
template&lt;typename Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre> <p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and <b>d</b>.</p>
<p>Constructs a <b>shared_ptr</b>, as if by storing a copy of the <p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p>
pointer stored in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> <p><b>Throws:</b> <b>std::bad_alloc</b>.</p>
for all copies is 1 more than the initial use count, or 1 <p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p>
in the <b>auto_ptr</b> case. In the <b>auto_ptr</b> case, <b>r.release()</b> <p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
is called. <code>d(p)</code> is invoked.</p>
The only exception which may be thrown is <b>std::bad_alloc</b>, </blockquote>
which may be thrown during construction from <b>auto_ptr</b>. <pre>shared_ptr(shared_ptr const &amp; r); // never throws
If an exception is thrown, the constructor has no effect.</p> template&lt;typename Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote>
<h3><a name="destructor">destructor</a></h3> <p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
pointer stored in <STRONG>r</STRONG>.</p>
<pre>~shared_ptr(); // never throws</pre> <p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0, increased by one.</p>
deletes the object pointed to by the stored pointer. <p><b>Throws:</b> nothing.</p>
Note that <b>delete</b> on a pointer with a value of 0 is harmless. </blockquote>
<b>T</b> need not be a complete type. <pre>shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const &amp; r);</pre>
The guarantee that this does not throw exceptions depends on the requirement that the <blockquote>
deleted object's destructor does not throw exceptions. <p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is
<h3><a name="operator=">assignment</a></h3> increased by one.</p>
<p><b>Throws:</b> <b>use_count_is_zero</b> when <code>r.use_count() == 0</code>.</p>
<pre>shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr const &amp; r); // never throws <p><b>Exception safety:</b> If an exception is thrown, the constructor has no
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(shared_ptr&lt;Y&gt; const &amp; r); // never throws effect.</p>
template&lt;typename Y&gt; shared_ptr &amp; <a href="#assignment">operator=</a>(std::auto_ptr&lt;Y&gt; &amp; r);</pre> </blockquote>
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>, <pre>template&lt;typename Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object. <BLOCKQUOTE>
The only exception which may be thrown is <b>std::bad_alloc</b>, <P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P>
which may be thrown during assignment from <b>auto_ptr</b>. <P><B>Postconditions:</B> <A href="#use_count">use count</A> for all copies is
If an exception is thrown, the assignment has no effect.</p> increased by one.</P>
<P><B>Throws:</B> <B>std::bad_alloc</B>.</P>
<h3><a name="reset">reset</a></h3> <P><B>Exception safety:</B> If an exception is thrown, the constructor has no
effect.</P>
<pre>void reset(T * p = 0);</pre> </BLOCKQUOTE>
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>, <h3><a name="destructor">destructor</a></h3>
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object. <pre>~shared_ptr(); // never throws</pre>
The only exception which may be thrown is <b>std::bad_alloc</b>. If <BLOCKQUOTE>
an exception is thrown, <b>delete p</b> is called.</p> <P><B>Effects:</B> If <STRONG>*this</STRONG> is the sole owner (<code>use_count() == 1</code>),
destroys the object pointed to by the stored pointer.</P>
<pre>template&lt;typename D&gt; void reset(T * p, D d);</pre> <P><B>Postconditions:</B> <A href="#use_count">use count</A> for all remaining
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>, copies is decreased by one.</P>
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object. <P><B>Throws:</B> nothing.</P>
<b>D</b>'s copy constructor must not throw. <P><B>Notes:</B> <B>T</B> need not be a complete type. The guarantee that the
The only exception which may be thrown is <b>std::bad_alloc</b>. If destructor does not throw exceptions depends on the requirement that the
an exception is thrown, <b>d(p)</b> is called.</p> 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> </BLOCKQUOTE>
<pre>T &amp; operator*() const; // never throws</pre> <H3><a name="assignment">assignment</a></H3>
<p>Returns a reference to the object pointed to by the stored pointer. <pre>shared_ptr &amp; operator=(shared_ptr const &amp; r); // never throws
Behavior is undefined if the stored pointer is 0.</p> template&lt;typename Y&gt; shared_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r); // never throws
<pre>T * operator-&gt;() const; // never throws</pre> template&lt;typename Y&gt; shared_ptr &amp; operator=(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p> <BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
<h3><a name="get">get</a></h3> </BLOCKQUOTE>
<pre>T * get() const; // never throws</pre> <h3><a name="reset">reset</a></h3>
<p>Returns the stored pointer. <pre>void reset(T * p = 0);</pre>
<b>T</b> need not be a complete type. <BLOCKQUOTE>
See the smart pointer <P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> </BLOCKQUOTE>
<pre>template&lt;typename D&gt; void reset(T * p, D d);</pre>
<h3><a name="unique">unique</a></h3> <BLOCKQUOTE>
<pre>bool unique() const; // never throws</pre> <P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
<p>Returns true if no other <b>shared_ptr</b> is sharing ownership of </BLOCKQUOTE>
the stored pointer, false otherwise. <h3><a name="indirection">indirection</a></h3>
<b>T</b> need not be a complete type. <pre>T &amp; operator*() const; // never throws</pre>
See the smart pointer <blockquote>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <p><b>Requirements:</b> The stored pointer must not be 0.</p>
<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
<h3><a name="use_count">use_count</a></h3> <p><b>Throws:</b> nothing.</p>
<pre>long use_count() const; // never throws</pre> </blockquote>
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the <pre>T * operator-&gt;() const; // never throws</pre>
stored pointer. <blockquote>
<b>T</b> need not be a complete type. <p><b>Requirements:</b> The stored pointer must not be 0.</p>
See the smart pointer <p><b>Returns:</b> the stored pointer.</p>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <p><b>Throws:</b> nothing.</p>
<p>Because <b>use_count</b> is not necessarily efficient to implement for </blockquote>
implementations of <b>shared_ptr</b> that do not use an explicit reference <h3><a name="get">get</a></h3>
count, it might be removed from some future version. Thus it should <pre>T * get() const; // never throws</pre>
be used for debugging purposes only, and not production code.</p> <blockquote>
<p><b>Returns:</b> the stored pointer.</p>
<h3><a name="swap">swap</a></h3> <p><b>Throws:</b> nothing.</p>
<pre>void swap(shared_ptr &amp; b); // never throws</pre> <P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
<p>Exchanges the contents of the two smart pointers. common requirements</A>.</P>
<b>T</b> need not be a complete type. </blockquote>
See the smart pointer <h3><a name="unique">unique</a></h3>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> <pre>bool unique() const; // never throws</pre>
<blockquote>
<h2><a name="functions">Free Functions</a></h2> <p><b>Returns:</b> <code>use_count() == 1</code>.</p>
<p><b>Throws:</b> nothing.</p>
<h3><a name="comparison">comparison</a></h3> <P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>. <B>T</B>
<pre>template&lt;typename T, typename U&gt; need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
bool operator==(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws common requirements</A>.</P>
template&lt;typename T, typename U&gt; </blockquote>
bool operator!=(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws <h3><a name="use_count">use_count</a></h3>
template&lt;typename T&gt; <pre>long use_count() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the
stored pointer.</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. <B>T</B> need not
be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;typename T, typename U&gt;
bool operator==(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<pre>template&lt;typename T, typename U&gt;
bool operator!=(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <B>T</B> need not be a complete type. See the smart pointer <A href="smart_ptr.htm#Common requirements">
common requirements</A>.</P>
</blockquote>
<pre>template&lt;typename T&gt;
bool operator&lt;(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws</pre> bool operator&lt;(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;T&gt; const &amp; b); // never throws</pre>
<p>Compares the stored pointers of the two smart pointers. <blockquote>
<b>T</b> need not be a complete type. <p><b>Returns:</b> An implementation-defined value such that <code>operator&lt;</code>
See the smart pointer is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p> of the C++ standard.</p>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_ptr</b> <p><b>Throws:</b> nothing.</p>
objects can be used in associative containers such as <b>std::map</b>. <P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
The implementation uses <b>std::less&lt;T *&gt;</b> to perform the associative containers. <B>T</B> need not be a complete type. See the smart
comparison. This ensures that the comparison is handled correctly, since the pointer <A href="smart_ptr.htm#Common requirements">common requirements</A>.</P>
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] </blockquote>
paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3 [lib.comparisons] <h3><a name="free-swap">swap</a></h3>
paragraph 8).</p> <pre>template&lt;typename T&gt;
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;typename T&gt;
void swap(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b) // never throws</pre> void swap(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b) // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>. <BLOCKQUOTE>
Provided as an aid to generic programming.</p> <P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<h3><a name="shared_static_cast">shared_static_cast</a></h3> <P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
<pre>template&lt;typename T, typename U&gt; generic programming.</P>
shared_ptr&lt;T&gt shared_static_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre> </BLOCKQUOTE>
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>shared_ptr</b>. <h3><a name="shared_static_cast">shared_static_cast</a></h3>
The resulting smart pointer will share its use count with the original pointer.</p> <pre>template&lt;typename T, typename U&gt;
<p>Note that the seemingly equivalent expression</p> shared_ptr&lt;T&gt; shared_static_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<blockquote><code>shared_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code></blockquote> <BLOCKQUOTE>
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p> <P><STRONG>Requires:</STRONG> The expression <code>static_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3> <P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
<pre>template&lt;typename T, typename U&gt; of <code>static_cast&lt;T*&gt;(r.get())</code> and shares ownership with <b>r</b>.</P>
shared_ptr&lt;T&gt shared_dynamic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre> <P><B>Throws:</B> nothing.</P>
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>shared_ptr</b>. <P><B>Notes:</B> the seemingly equivalent expression</P>
The resulting smart pointer will share its use count with the original pointer unless the result of the <p><code>shared_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code></p>
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the <p>will eventually result in undefined behavior, attempting to delete the same
construction of the new <b>shared_ptr</b> if the result of the cast is 0. If an exception is thrown, the object twice.</p>
cast has no effect.</p> </BLOCKQUOTE>
<p>Note that the seemingly equivalent expression</p> <h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
<blockquote><code>shared_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</code></blockquote> <pre>template&lt;typename T, typename U&gt;
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p> shared_ptr&lt;T&gt; shared_dynamic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3> <P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE>
<pre>template&lt;typename T, typename U&gt; must be well-formed and its behavior defined.</P>
shared_ptr&lt;T&gt shared_polymorphic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre> <P><B>Returns:</B></P>
<p>Perform a <a href="../conversion/cast.htm#Polymorphic_cast"><b>polymorphic_cast</b><a> on the stored pointer, <UL>
returning another <b>shared_ptr</b>. <LI>
The resulting smart pointer will share its use count with the original pointer. When <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> returns a nonzero
The only exception which may be thrown is <b>std::bad_cast</b>, if the pointer type can not be converted. value,&nbsp;a <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy of
If an exception is thrown, the cast has no effect.</p> it and shares ownership with <STRONG>r</STRONG>;
<LI>
<h3><a name="shared_polymorphic_downcast">shared_polymorphic_downcast</a></h3> Otherwise, a default-constructed <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL>
<pre>template&lt;typename T, typename U&gt; <P><B>Throws:</B> <STRONG>std::bad_alloc</STRONG>.</P>
shared_ptr&lt;T&gt shared_polymorphic_downcast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre> <P><B>Exception safety:</B> If an exception is thrown, the&nbsp;function has no
<p>Perform a <a href="../conversion/cast.htm#Polymorphic_cast"><b>polymorphic_downcast</b><a> on the stored pointer, effect.</P>
returning another <b>shared_ptr</b>. <P><B>Notes:</B> the seemingly equivalent expression</P>
The resulting smart pointer will share its use count with the original pointer.</p> <P><CODE>shared_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</CODE></P>
<P>will eventually result in undefined behavior, attempting to delete the same
<h2><a name="example">Example</a></h2> object twice.</P>
</BLOCKQUOTE>
<p>See <a href="shared_ptr_example.cpp">shared_ptr_example.cpp</a> for a complete example program. <h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3>
The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b> objects.</p> <pre>template&lt;typename T, typename U&gt;
shared_ptr&lt;T&gt; shared_polymorphic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b> objects <BLOCKQUOTE>
will have a use count of 1 rather than a use count of 2, since the set is a <b>std::set</b> <p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
rather than a <b>std::multiset</b>, and thus does not contain duplicate entries. polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed and
Furthermore, the use count may be even higher its behavior defined.</p>
at various times while <b>push_back</b> and <b>insert</b> container operations are performed. <P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
More complicated yet, the container operations may throw exceptions under a of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE>
variety of circumstances. Getting the memory management and exception handling in this and shares ownership with <B>r</B>.</P>
example right without a smart pointer would be a nightmare.</p> <P><B>Throws:</B> <STRONG>std::bad_cast</STRONG>.</P>
<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2> </BLOCKQUOTE>
<h3><a name="shared_polymorphic_downcast">shared_polymorphic_downcast</a></h3>
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also <pre>template&lt;typename T, typename U&gt;
called pimpl) idiom which avoids exposing the body (implementation) in the header shared_ptr&lt;T&gt; shared_polymorphic_downcast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
file.</p> <BLOCKQUOTE>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
<p>The <a href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</a> polymorphic_downcast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed
sample program includes a header file, <a href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</a>, and its behavior defined.</p>
which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the <P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy
implementation. The of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_downcast</A>&lt;T*&gt;(r.get())</CODE>
instantiation of member functions which require a complete type occurs in the and shares ownership with <B>r</B>.</P>
<a href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</a> <P><B>Throws:</B> nothing.</P>
implementation file. </BLOCKQUOTE>
Note that there is no need for an explicit destructor. <h2><a name="example">Example</a></h2>
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete type.</p> <p>See <A href="shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a complete
example program. The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b>
<h2><a name="FAQ">Frequently Asked Questions</a></h2> objects.</p>
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> have template parameters supplying objects will have a use count of 1 rather than a use count of 2, since the set
traits or policies to allow extensive user customization?<br> is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not
<b>A.</b> Parameterization discourages users. The <b>shared_ptr</b> template is contain duplicate entries. Furthermore, the use count may be even higher at
carefully crafted to meet common needs without extensive parameterization. various times while <b>push_back</b> and <b>insert</b> container operations are
Some day a highly configurable smart pointer may be invented that is also very performed. More complicated yet, the container operations may throw exceptions
easy to use and very hard to misuse. Until then, <b>shared_ptr</b> is the under a variety of circumstances. Getting the memory management and exception
smart pointer of choice for a wide range of applications. (Those handling in this example right without a smart pointer would be a nightmare.</p>
interested in policy based smart pointers should read <h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<a href="http://cseng.aw.com/book/0,,0201704315,00.html">Modern C++ Design</a> by Andrei Alexandrescu.)</p> <p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br> file.</p>
<b>A.</b> A linked list implementation does not offer enough advantages to <p>The <A href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A> sample
offset the added cost of an extra pointer. See <a href="smarttests.htm">timings</a> program includes a header file, <A href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
page.</p> which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart pointers) type occurs in the <A href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
supply an automatic conversion to <b>T*</b>?<br> implementation file. Note that there is no need for an explicit destructor.
<b>A.</b> Automatic conversion is believed to be too error prone.</p> Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete
type.</p>
<p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br> <h2><a name="FAQ">Frequently Asked Questions</a></h2>
<b>A.</b> As an aid to writing test cases and debugging displays. One of the <P><B>Q.</B> There are several variations of shared pointers, with different
progenitors had use_count(), and it was useful in tracking down bugs in a tradeoffs; why does the smart pointer library supply only a single
complex project that turned out to have cyclic-dependencies.</p> 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?<BR>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br> <b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
<b>A.</b> Because complexity requirements limit implementors and complicate the standard shared-ownership pointer. Having a single pointer type is important
specification without apparent benefit to <b>shared_ptr</b> users. for stable library interfaces, since different shared pointers typically cannot
For example, error-checking implementations might become non-conforming if they interoperate, i.e. a reference counted pointer (used by library A) cannot share
had to meet stringent complexity requirements.</p> ownership with a linked pointer (used by library B.)</P>
<P><B>Q.</B> Why doesn't <B>shared_ptr</B> have template parameters supplying
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?<br> traits or policies to allow extensive user customization?<BR>
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique() <B>A.</B> Parameterization discourages users. The <B>shared_ptr</B> template is
because the other copy will still destroy the object.</p> carefully crafted to meet common needs without extensive parameterization. Some
<p>Consider:</p> day a highly configurable smart pointer may be invented that is also very easy
<blockquote><pre>shared_ptr&lt;int&gt; a(new int); to use and very hard to misuse. Until then, <B>shared_ptr</B> is the smart
pointer of choice for a wide range of applications. (Those interested in policy
based smart pointers should read <A href="http://cseng.aw.com/book/0,,0201704315,00.html">
Modern C++ Design</A> by Andrei Alexandrescu.)</P>
<P><B>Q.</B> I am not convinced. Default parameters can be use where appropriate to
hide the complexity. Again, why not policies?<BR>
<B>A.</B> Template parameters affect the type. See the answer to the first
question above.</P>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
<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 <b>shared_ptr</b> (or any of the other Boost smart
pointers) supply an automatic conversion to <b>T*</b>?<br>
<b>A.</b> Automatic conversion is believed to be too error prone.</p>
<p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br>
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
progenitors had use_count(), and it was useful in tracking down bugs in a
complex project that turned out to have cyclic-dependencies.</p>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br>
<b>A.</b> Because complexity requirements limit implementors and complicate the
specification without apparent benefit to <b>shared_ptr</b> 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 <b>shared_ptr</b> provide a release() function?<br>
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
because the other copy will still destroy the object.</p>
<p>Consider:</p>
<blockquote><pre>shared_ptr&lt;int&gt; a(new int);
shared_ptr&lt;int&gt; b(a); // a.use_count() == b.use_count() == 2 shared_ptr&lt;int&gt; b(a); // a.use_count() == b.use_count() == 2
int * p = a.release(); int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.</pre></blockquote> // Who owns p now? b will still call delete on it in its destructor.</pre>
</blockquote>
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br> <p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br>
<b>A.</b> Because (your pet feature here) would mandate a reference counted <b>A.</b> Because (your pet feature here) would mandate a reference counted
implementation or a linked list implementation, or some other specific implementation. implementation or a linked list implementation, or some other specific
This is not the intent.</p> implementation. This is not the intent.</p>
<hr>
<hr> <p>Revised&nbsp; <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
14 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->8 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p> <p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. distribute this document is granted provided this copyright notice appears in
Permission to copy, use, modify, sell and distribute this document is granted all copies. This document is provided "as is" without express or implied
provided this copyright notice appears in all copies. warranty, and with no claim as to its suitability for any purpose.</p>
This document is provided &quot;as is&quot; without express or implied warranty, </body>
and with no claim as to its suitability for any purpose.</p>
</body>
</html> </html>