Documentation updated to reflect changes to shared_ptr

[SVN r16739]
This commit is contained in:
Peter Dimov
2003-01-03 16:53:04 +00:00
parent fafd9a863b
commit 987a7d32fb
2 changed files with 117 additions and 150 deletions

View File

@@ -106,7 +106,7 @@ public:
typedef T * pointer; typedef T * pointer;
typedef typename detail::shared_ptr_traits<T>::reference reference; typedef typename detail::shared_ptr_traits<T>::reference reference;
shared_ptr(): px(0), pn() shared_ptr(): px(0), pn() // never throws in 1.30+
{ {
} }
@@ -211,7 +211,7 @@ public:
#endif #endif
void reset() void reset() // never throws in 1.30+
{ {
this_type().swap(*this); this_type().swap(*this);
} }
@@ -253,6 +253,8 @@ public:
return px == 0? 0: &this_type::get; return px == 0? 0: &this_type::get;
} }
// operator! is redundant, but some compilers need it
bool operator! () const // never throws bool operator! () const // never throws
{ {
return px == 0; return px == 0;

View File

@@ -8,13 +8,13 @@
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_ptr <h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_ptr
class template</h1> class template</h1>
<p><A href="#Introduction">Introduction</A><br> <p><A href="#Introduction">Introduction</A><br>
<a href="#BestPractices">Best Practices</a><br> <A href="#BestPractices">Best Practices</A><br>
<A href="#Synopsis">Synopsis</A><br> <A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br> <A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br> <A href="#functions">Free Functions</A><br>
<A href="#example">Example</A><br> <A href="#example">Example</A><br>
<A href="#Handle/Body">Handle/Body Idiom</A><br> <A href="#Handle/Body">Handle/Body Idiom</A><br>
<a href="#ThreadSafety">Thread Safety</a><br> <A href="#ThreadSafety">Thread Safety</A><br>
<A href="#FAQ">Frequently Asked Questions</A><br> <A href="#FAQ">Frequently Asked Questions</A><br>
<A href="smarttests.htm">Smart Pointer Timings</A></p> <A href="smarttests.htm">Smart Pointer Timings</A></p>
<h2><a name="Introduction">Introduction</a></h2> <h2><a name="Introduction">Introduction</a></h2>
@@ -60,8 +60,7 @@
be rare.</P> be rare.</P>
<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to <P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to
see why this is dangerous, consider this example:</P> see why this is dangerous, consider this example:</P>
<PRE> <PRE>void f(shared_ptr&lt;int&gt;, int);
void f(shared_ptr&lt;int&gt;, int);
int g(); int g();
void ok() void ok()
@@ -86,7 +85,7 @@ void bad()
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost { <pre>namespace boost {
class use_count_is_zero: public std::exception; class bad_weak_ptr: public std::exception;
template&lt;class T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>; template&lt;class T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>;
@@ -96,21 +95,21 @@ void bad()
typedef T <A href="#element_type" >element_type</A>; typedef T <A href="#element_type" >element_type</A>;
<A href="#constructors">shared_ptr</A>(); <A href="#constructors" >shared_ptr</A>(); // never throws
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(Y * p); template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(Y * p);
template&lt;class Y, class D&gt; <A href="#constructors" >shared_ptr</A>(Y * p, D d); template&lt;class Y, class D&gt; <A href="#constructors" >shared_ptr</A>(Y * 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;class Y&gt; <A href="#constructors">shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;class Y&gt; <A href="#constructors" >shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; explicit <A href="#constructors">shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r); template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(std::auto_ptr&lt;Y&gt; &amp; r); template&lt;class Y&gt; explicit <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;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r); template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r);
void <A href="#reset" >reset</A>(); void <A href="#reset" >reset</A>(); // never throws
template&lt;class Y&gt; void <A href="#reset" >reset</A>(Y * p); template&lt;class Y&gt; void <A href="#reset" >reset</A>(Y * p);
template&lt;class Y, class D&gt; void <A href="#reset" >reset</A>(Y * p, D d); template&lt;class Y, class D&gt; void <A href="#reset" >reset</A>(Y * p, D d);
@@ -121,37 +120,39 @@ void bad()
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
operator <a href="#conversions"><i>unspecified-bool-type</i></a>() const; // never throws operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <A href="#swap" >swap</A>(shared_ptr &amp; b); // never throws void <A href="#swap" >swap</A>(shared_ptr &amp; b); // never throws
}; };
template&lt;class T, class U&gt; template&lt;class T, class 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;class T, class U&gt; template&lt;class T, class 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;class 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 template&lt;class T, class U&gt;
bool <A href="#comparison" >operator&lt;</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class 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;class 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;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(shared_ptr&lt;T&gt; const &amp; p); // never throws template&lt;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(shared_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;class T, class U&gt; template&lt;class T, class 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="#static_pointer_cast" >static_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt; template&lt;class T, class 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="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr&lt;U&gt; const &amp; r); template&lt;class E, class T, class Y&gt;
template&lt;class T, class U&gt; std::basic_ostream&lt;E, T&gt; &amp; <A href="#insertion-operator" >operator&lt;&lt;</A> (std::basic_ostream&lt;E, T&gt; &amp; os, shared_ptr&lt;Y&gt; const &amp; p);
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>
<P><EM>[It might be convenient to relax the requirements on <STRONG>shared_ptr</STRONG>'s <P><EM>[It might be convenient to relax the requirements on <STRONG>shared_ptr</STRONG>'s
signature, allowing an additional, defaulted, template parameter; the parameter signature, allowing an additional, defaulted, template parameter; the parameter
can encode the threading model, for example. This would help in detecting can encode the threading model, for example. This would help in detecting
possible ODR violations.</EM></P> possible ODR violations.</EM></P>
<P><EM> On the other hand, using <STRONG>shared_ptr</STRONG> as an argument to a <P><EM>On the other hand, using <STRONG>shared_ptr</STRONG> as an argument to a
template template parameter requires an exact signature match. </EM><EM>Metaprogramming template template parameter requires an exact signature match. </EM><EM>Metaprogramming
experts tend to deemphasize template template parameters as they are too experts tend to deemphasize template template parameters as they are too
inflexible, but the alternative is typically an std::allocator::rebind-type inflexible, but the alternative is typically an std::allocator::rebind-type
@@ -163,27 +164,22 @@ void bad()
<p>Provides the type of the template parameter T.</p> <p>Provides the type of the template parameter T.</p>
</blockquote> </blockquote>
<h3><a name="constructors">constructors</a></h3> <h3><a name="constructors">constructors</a></h3>
<pre>shared_ptr();</pre> <pre>shared_ptr(); // never throws</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>.</p> <p><b>Effects:</b> Constructs an <EM>empty</EM> <b>shared_ptr</b>. <EM>Empty</EM> <STRONG>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1; the stored shared_ptr</STRONG> objects have an unspecified <A href="#use_count">use_count</A>.</p>
pointer is 0.</p> <p><b>Postconditions:</b> <code>get() == 0</code>.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p> <p><b>Throws:</b> nothing.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
</blockquote> </blockquote>
<P><EM>[The postcondition of use_count() == 1 is too strong. Having the nothrow <P><EM>[The nothrow guarantee is important, since <STRONG>reset()</STRONG> is specified
guarantee is important, since <STRONG>reset()</STRONG> is specified in terms of in terms of the default constructor; this implies that the constructor must not
the default constructor, but the current specification requires that a count be allocate memory.</EM></P>
allocated. Therefore, this postcondition will be dropped in a future release. <P><EM>There are two possible implementations, one stores 0 as a pointer to the
The use count of a default-constructed <STRONG>shared_ptr</STRONG>, including
all copies created from it, will probably be left unspecified.</EM></P>
<P><EM>There are two possible nothrow implementations, one stores 0 as a pointer to the
reference count, the other uses a single statically allocated count for all reference count, the other uses a single statically allocated count for all
default-constructed <STRONG>shared_ptr</STRONG>s. The second option is default-constructed <STRONG>shared_ptr</STRONG>s. The second option is
difficult to achieve in the current header-only reference implementation due to difficult to achieve in the current header-only reference implementation due to
thread safety issues and initialization order, but it should not be precluded thread safety issues and initialization order, but it should not be precluded
by the specification.</EM></P> by the specification. That's why the use_count() has been left unspecified.</EM></P>
<P><EM>A future release may enable <STRONG>shared_ptr</STRONG> construction from a <P><EM>A future release may enable <STRONG>shared_ptr</STRONG> construction from a
literal zero, for consistency with built-in pointers. It is not clear yet literal zero, for consistency with built-in pointers. It is not clear yet
whether this constructor should be left implicit, enabling <STRONG>0</STRONG> to whether this constructor should be left implicit, enabling <STRONG>0</STRONG> to
@@ -195,8 +191,9 @@ void bad()
well-formed, must not invoke undefined behavior, and must not throw exceptions. well-formed, must not invoke undefined behavior, and must not throw exceptions.
</p> </p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>.</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>Postconditions:</b> <code>use_count() == 1 &amp;&amp; get() == p</code>.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p> <p><b>Throws:</b> <b>std::bad_alloc</b> 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>delete p</code> is <p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is
called.</p> called.</p>
<P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was <P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was
@@ -208,28 +205,11 @@ void bad()
pointer type passed. The destructor will call <STRONG>delete</STRONG> with the pointer type passed. The destructor will call <STRONG>delete</STRONG> with the
same pointer, complete with its original type, even when <STRONG>T</STRONG> does same pointer, complete with its original type, even when <STRONG>T</STRONG> does
not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P> not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P>
<P><EM>In the current implementation, if <STRONG>p</STRONG> is convertible to <STRONG>counted_base <P><EM>The optional intrusive counting support has been dropped as it exposes too much
*</STRONG>, <STRONG>shared_ptr</STRONG> will use the embedded reference implementation details and doesn't interact well with <STRONG>weak_ptr</STRONG>.
count supplied by <STRONG>counted_base</STRONG>. This is an (experimental) The current implementation uses a different mechanism, <A href="enable_shared_from_this.html">
attempt to provide a way for <STRONG>shared_ptr</STRONG> to be constructed from enable_shared_from_this</A>, to solve the "<STRONG>shared_ptr</STRONG> from <STRONG>
a raw pointer such as <STRONG>this</STRONG>. A free function <STRONG>shared_from_this(q)</STRONG> this</STRONG>" problem.</EM><EM>]</EM></P>
performs the conversion when <STRONG>q</STRONG> is convertible to <STRONG>counted_base
const *</STRONG>.</EM></P>
<P><EM>The optional intrusive counting employed by the current implementation allows <STRONG>
shared_ptr</STRONG> to interoperate with <STRONG>intrusive_ptr</STRONG>, an
experimental generic intrusive-counted smart pointer.</EM></P>
<P><EM> Another possible implementation is to use a global pointer-to-count map instead
of intrusive counting. <STRONG>shared_from_this</STRONG> would no longer be
O(1), which is a concern for some users, although I do not expect any
performance problems, since the operation is rare. Maintaining a global map is
difficult; it needs to be initialized before any <STRONG>shared_ptr</STRONG> instances
are constructed, and the initialization needs to be thread safe. In addition,
under the Windows dynamic library model, it is possible for several maps to
exist.</EM></P>
<P><EM> It is not yet clear which implementation should be used, or whether the
specification should allow both; nevertheless, the ability to make a <STRONG>shared_ptr</STRONG>
from <STRONG>this</STRONG> is considered essential by experienced smart pointer
users.</EM><EM>]</EM></P>
<pre>template&lt;class Y, class D&gt; shared_ptr(Y * p, D d);</pre> <pre>template&lt;class Y, class D&gt; shared_ptr(Y * p, D d);</pre>
<blockquote> <blockquote>
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. <STRONG>D</STRONG> <p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. <STRONG>D</STRONG>
@@ -238,8 +218,9 @@ void bad()
well-formed, must not invoke undefined behavior, and must not throw exceptions. well-formed, must not invoke undefined behavior, and must not throw exceptions.
</p> </p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and <b>d</b>.</p> <p><b>Effects:</b> Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and <b>d</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1.</p> <p><b>Postconditions:</b> <code>use_count() == 1 &amp;&amp; get() == p</code>.</p>
<p><b>Throws:</b> <b>std::bad_alloc</b>.</p> <p><b>Throws:</b> <b>std::bad_alloc</b> 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>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>, <p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
the stored copy of <STRONG>d</STRONG> is invoked with the stored copy of <STRONG>p</STRONG> the stored copy of <STRONG>d</STRONG> is invoked with the stored copy of <STRONG>p</STRONG>
@@ -250,38 +231,39 @@ void bad()
is not part of the type, changing the allocation strategy does not break source 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 or binary compatibility, and does not require a client recompilation. For
example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG> example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG>
to a statically allocated object.</EM></P> to a statically allocated object, and other variations allow a <STRONG>shared_ptr</STRONG>
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 <STRONG> <P><EM>The support for custom deallocators does not impose significant overhead. Other <STRONG>
shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P> shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P>
<P><EM>The requirement that the copy constructor of <b>D</b> does not throw comes from <P><EM>The requirement that the copy constructor of <b>D</b> does not throw comes from
the pass by value. If the copy constructor throws, the pointer is leaked. the pass by value. If the copy constructor throws, the pointer is leaked.
Removing the requirement requires a pass by (const) reference. The problems are Removing the requirement requires a pass by (const) reference.</EM></P>
that (1) pass by value conveniently changes functions (function references) to <P><EM>Pass by reference is problematic since (1) pass by value conveniently changes
function pointers (this has to be performed manually otherwise and some functions (function references) to function pointers (this has to be performed
compilers may not be able to do it) and (2) const references don't currently manually otherwise and some compilers may not be able to do it) and (2) const
(per the standard) bind to functions. This can be solved (I think) but it references don't currently (per the standard) bind to functions. This can be
requires an overload set that breaks on many compilers due to 14.5.5.2 problems solved (I think) but it requires an overload set that breaks on many compilers
(and of course it will break on compilers that don't do partial ordering at due to 14.5.5.2 problems (and of course it will break on compilers that don't
all.)</EM></P> do partial ordering at all.)</EM></P>
<P><EM>The requrement will be removed when the aforementioned issues are resolved.]</EM></P> <P><EM>The main problem with pass by reference, though, lies in its interaction with
rvalues. A const reference may still cause a copy, and will require a const
operator(). A non-const reference won't bind to an rvalue at all. A good
solution to this problem is the rvalue reference proposed in <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">
N1377</A>/<A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">N1385</A>.]</EM></P>
<pre>shared_ptr(shared_ptr const &amp; r); // never throws <pre>shared_ptr(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre> template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the <p><b>Effects:</b> If <b>r</b> is <EM>empty</EM>, constructs an <EM>empty</EM> <b>shared_ptr</b>;
pointer stored in <STRONG>r</STRONG>.</p> otherwise, constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with <b>r</b>.</p>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is <p><b>Postconditions:</b> <code>get() == r.get()</code>.</p>
increased by one.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<P><EM>[The postcondition will be relaxed when a default-constructed <STRONG>shared_ptr</STRONG> <pre>template&lt;class Y&gt; explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);</pre>
is being copied.]</EM></P>
<pre>template&lt;class Y&gt; explicit shared_ptr(<A href="weak_ptr.htm">weak_ptr</A>&lt;Y&gt; const &amp; r);</pre>
<blockquote> <blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>, as if by storing a copy of the <p><b>Effects:</b> If <b>r</b> is <EM>empty</EM>, constructs an <EM>empty</EM> <b>shared_ptr</b>;
pointer stored in <STRONG>r</STRONG>.</p> otherwise, constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with <b>r</b>
<p><b>Postconditions:</b> <A href="#use_count">use count</A> for all copies is and stores a copy of the pointer&nbsp;stored in <STRONG>r</STRONG>.</p>
increased by one.</p> <p><b>Throws:</b>&nbsp;<b>bad_weak_ptr</b> when <code>r.use_count() == 0</code>.</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 <p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p> effect.</p>
</blockquote> </blockquote>
@@ -299,21 +281,22 @@ template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never
<pre>template&lt;class Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre> <pre>template&lt;class Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE> <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>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> is 1.</P> <p><b>Postconditions:</b> <code>use_count() == 1</code>.</p>
<P><B>Throws:</B> <B>std::bad_alloc</B>.</P> <p><b>Throws:</b> <b>std::bad_alloc</b> 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 <P><B>Exception safety:</B> If an exception is thrown, the constructor has no
effect.</P> effect.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and <P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and
not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is
by design, as the constructor offers the strong guarantee.]</EM></P> by design, as the constructor offers the strong guarantee; an rvalue reference
would solve this problem, too.]</EM></P>
<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>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> If <STRONG>*this</STRONG> is the sole owner (<code>use_count() == 1</code>), <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> destroys the object pointed to by the stored pointer as specified at
<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all remaining construction time.</P>
copies is decreased by one.</P>
<P><B>Throws:</B> nothing.</P> <P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<H3><a name="assignment">assignment</a></H3> <H3><a name="assignment">assignment</a></H3>
@@ -327,8 +310,7 @@ template&lt;class Y&gt; shared_ptr &amp; operator=(std::auto_ptr&lt;Y&gt; &amp;
and destruction are not considered observable side effects, and the and destruction are not considered observable side effects, and the
implementation is free to meet the effects (and the implied guarantees) via implementation is free to meet the effects (and the implied guarantees) via
different means, without creating a temporary. In particular, in the example:</P> different means, without creating a temporary. In particular, in the example:</P>
<pre> <pre>shared_ptr&lt;int&gt; p(new int);
shared_ptr&lt;int&gt; p(new int);
shared_ptr&lt;void&gt; q(p); shared_ptr&lt;void&gt; q(p);
p = p; p = p;
q = p; q = p;
@@ -342,12 +324,10 @@ q = p;
actually applies here, so it's better to be explicit about the possible actually applies here, so it's better to be explicit about the possible
optimizations.]</EM></P> optimizations.]</EM></P>
<h3><a name="reset">reset</a></h3> <h3><a name="reset">reset</a></h3>
<pre>void reset();</pre> <pre>void reset(); // never throws</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P> <P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<P><EM>[<STRONG>reset()</STRONG> will offer the nothrow guarantee in a future
implementation.]</EM></P>
<pre>template&lt;class Y&gt; void reset(Y * p);</pre> <pre>template&lt;class Y&gt; void reset(Y * p);</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P> <P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
@@ -384,13 +364,12 @@ q = p;
If you are using <code>unique()</code> to implement copy on write, do not rely 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> on a specific value when the stored pointer is zero.</P>
</blockquote> </blockquote>
<P><EM>[In a future release, <STRONG>unique()</STRONG> will return an unspecified value
for a default-constructed <STRONG>shared_ptr.</STRONG>]</EM></P>
<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>
<blockquote> <blockquote>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects sharing ownership of the <p><b>Returns:</b> the number of <b>shared_ptr</b> objects that <i>share ownership</i>
stored pointer.</p> with <b>*this</b>, or an unspecified nonnegative value when <STRONG>*this</STRONG>
is <EM>empty</EM>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only <P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
for debugging and testing purposes, not for production code.</P> for debugging and testing purposes, not for production code.</P>
@@ -407,8 +386,8 @@ q = p;
many of the implicit conversion pitfalls.</P> many of the implicit conversion pitfalls.</P>
</blockquote> </blockquote>
<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s <P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s
to be declared in conditions when using <STRONG>shared_dynamic_cast </STRONG>or <STRONG> to be declared in conditions when using <STRONG>dynamic_pointer_cast </STRONG>or
make_shared</STRONG>.]</EM></P> <STRONG>make_shared</STRONG>.]</EM></P>
<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>
<blockquote> <blockquote>
@@ -429,12 +408,18 @@ q = p;
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p> <p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
</blockquote> </blockquote>
<pre>template&lt;class T&gt; <pre>template&lt;class T, class U&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;U&gt; const &amp; b); // never throws</pre>
<blockquote> <blockquote>
<p><b>Returns:</b> an unspecified value such that <b>operator&lt;</b> is a strict <p><b>Returns:</b> an unspecified value such that</p>
weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code> of <UL>
the C++ standard.</p> <LI>
<b>operator&lt;</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&lt;</STRONG>, <code>!(a
&lt; b) &amp;&amp; !(b &lt; a)</code>, two <STRONG>shared_ptr</STRONG> instances
are equivalent if and only if they <EM>share ownership</EM>.</LI></UL>
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in <P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
associative containers.</P> associative containers.</P>
@@ -468,23 +453,24 @@ q = p;
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html"> <P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
mem_fn</A>.</P> mem_fn</A>.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="shared_static_cast">shared_static_cast</a></h3> <h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class 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; static_pointer_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <code>static_cast&lt;T*&gt;(r.get())</code> <P><STRONG>Requires:</STRONG> The expression <code>static_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P> must be well-formed.</P>
<P><B>Returns:</B> A <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy <P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr&lt;T&gt;</b>;
of <code>static_cast&lt;T*&gt;(r.get())</code> and shares ownership with <b>r</b>.</P> otherwise, a <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy of <code>
static_cast&lt;T*&gt;(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
<P><B>Throws:</B> nothing.</P> <P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</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><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 <p>will eventually result in undefined behavior, attempting to delete the same
object twice.</p> object twice.</p>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3> <h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; shared_dynamic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre> shared_ptr&lt;T&gt; dynamic_pointer_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> <P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE>
must be well-formed and its behavior defined.</P> must be well-formed and its behavior defined.</P>
@@ -492,42 +478,22 @@ q = p;
<UL> <UL>
<LI> <LI>
When <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> returns a nonzero value, a <STRONG> When <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> returns a nonzero value, a <STRONG>
shared_ptr&lt;T&gt;</STRONG> object that stores a copy of it and shares shared_ptr&lt;T&gt;</STRONG> object that stores a copy of it and <i>shares
ownership with <STRONG>r</STRONG>; ownership</i> with <STRONG>r</STRONG>;
<LI> <LI>
Otherwise, a default-constructed <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL> Otherwise, an <i>empty</i> <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL>
<P><B>Throws:</B> <STRONG>std::bad_alloc</STRONG>.</P> <P><B>Throws:</B> nothing.</P>
<P><B>Exception safety:</B> If an exception is thrown, the function has no effect.</P>
<P><B>Notes:</B> the seemingly equivalent expression</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><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 <P>will eventually result in undefined behavior, attempting to delete the same
object twice.</P> object twice.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="shared_polymorphic_cast">shared_polymorphic_cast</a></h3> <h3><a name="insertion-operator">operator&lt;&lt;</a></h3>
<pre>template&lt;class T, class U&gt; <pre>template&lt;class E, class T, class Y&gt;
shared_ptr&lt;T&gt; shared_polymorphic_cast(shared_ptr&lt;U&gt; const &amp; r);</pre> std::basic_ostream&lt;E, T&gt; &amp; operator&lt;&lt; (std::basic_ostream&lt;E, T&gt; &amp; os, shared_ptr&lt;Y&gt; const &amp; p);</pre>
<BLOCKQUOTE> <BLOCKQUOTE>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast"> <p><STRONG>Effects:</STRONG> <code>os &lt;&lt; p.get();</code>.</p>
polymorphic_cast</A>&lt;T*&gt;(r.get())</CODE> must be well-formed and <P><B>Returns:</B> <b>os</b>.</P>
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_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> when the pointer cannot be
converted.</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>
<pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; shared_polymorphic_downcast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
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> </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
@@ -563,8 +529,7 @@ q = p;
underneath.)</p> underneath.)</p>
<P>Any other simultaneous accesses result in undefined behavior.</P> <P>Any other simultaneous accesses result in undefined behavior.</P>
<P>Examples:</P> <P>Examples:</P>
<pre> <pre>shared_ptr&lt;int&gt; p(new int(42));
shared_ptr&lt;int&gt; p(new int(42));
//--- Example 1 --- //--- Example 1 ---
@@ -577,7 +542,6 @@ shared_ptr&lt;int&gt; p3(p); // OK, multiple reads are safe
//--- Example 2 --- //--- Example 2 ---
// thread A // thread A
p.reset(new int(1912)); // writes p p.reset(new int(1912)); // writes p
// thread B // thread B
@@ -668,11 +632,12 @@ int * p = a.release();
implementation or a linked list implementation, or some other specific implementation or a linked list implementation, or some other specific
implementation. This is not the intent.</p> implementation. This is not the intent.</p>
<hr> <hr>
<p>Revised $Date$</p> <p>
$Date$</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.
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and Copyright 2002, 2003&nbsp;Peter Dimov. Permission to copy, use, modify, sell
distribute this document is granted provided this copyright notice appears in and distribute this document is granted provided this copyright notice appears
all copies. This document is provided "as is" without express or implied 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> warranty, and with no claim as to its suitability for any purpose.</p>
</body> </body>
</html> </html>