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