2002-02-02 18:36:12 +00:00
|
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
2000-07-27 14:27:00 +00:00
|
|
|
<html>
|
2002-02-14 17:12:07 +00:00
|
|
|
<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 {
|
|
|
|
|
2002-02-15 13:31:58 +00:00
|
|
|
class use_count_is_zero: public std::exception;
|
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
template<typename T> class <A href="weak_ptr.htm" >weak_ptr</A>;
|
2002-02-02 18:36:12 +00:00
|
|
|
|
|
|
|
template<typename T> class shared_ptr {
|
|
|
|
|
|
|
|
public:
|
2002-02-14 17:12:07 +00:00
|
|
|
typedef T <A href="#element_type" >element_type</A>;
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-15 13:31:58 +00:00
|
|
|
<A href="#constructors" >shared_ptr</A> ();
|
|
|
|
explicit <A href="#constructors" >shared_ptr</A> (T * p); // requires complete type
|
2002-02-14 17:12:07 +00:00
|
|
|
template<typename D> <A href="#constructors" >shared_ptr</A>(T * p, D d);
|
|
|
|
<A href="#destructor" >~shared_ptr</A>(); // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
<A href="#constructors" >shared_ptr</A>(shared_ptr const & r); // never throws
|
|
|
|
template<typename Y> <A href="#constructors" >shared_ptr</A>(shared_ptr<Y> const & r); // never throws
|
2002-02-15 13:31:58 +00:00
|
|
|
explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A> const & r);
|
2002-02-14 17:12:07 +00:00
|
|
|
template<typename Y> <A href="#constructors" >shared_ptr</A>(std::auto_ptr<Y> & r);
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr const & r); // never throws
|
|
|
|
template<typename Y> shared_ptr & <A href="#assignment" >operator=</A>(shared_ptr<Y> const & r); // never throws
|
|
|
|
template<typename Y> shared_ptr & <A href="#assignment" >operator=</A>(std::auto_ptr<Y> & r);
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-15 13:31:58 +00:00
|
|
|
void <A href="#reset" >reset</A> ();
|
|
|
|
void <A href="#reset" >reset</A> (T * p); // requires complete type
|
2002-02-14 17:12:07 +00:00
|
|
|
template<typename D> void <A href="#reset" >reset</A>(T * p, D d);
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
T & <A href="#indirection" >operator*</A>() const; // never throws
|
|
|
|
T * <A href="#indirection" >operator-></A>() const; // never throws
|
|
|
|
T * <A href="#get" >get</A>() const; // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
bool <A href="#unique" >unique</A>() const; // never throws
|
|
|
|
long <A href="#use_count" >use_count</A>() const; // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-15 14:46:53 +00:00
|
|
|
operator <a href="#conversions"><i>implementation-defined-type</i></a> () const; // never throws
|
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
void <A href="#swap" >swap</A>(shared_ptr<T> & b); // never throws
|
2000-07-27 14:27:00 +00:00
|
|
|
};
|
|
|
|
|
2002-02-02 18:36:12 +00:00
|
|
|
template<typename T, typename U>
|
2002-02-14 17:12:07 +00:00
|
|
|
bool <A href="#comparison" >operator==</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
template<typename T, typename U>
|
2002-02-14 17:12:07 +00:00
|
|
|
bool <A href="#comparison" >operator!=</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
2002-02-08 20:45:04 +00:00
|
|
|
template<typename T>
|
2002-02-14 17:12:07 +00:00
|
|
|
bool <A href="#comparison" >operator<</A>(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
template<typename T> void <A href="#free-swap" >swap</A>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
2002-02-14 17:12:07 +00:00
|
|
|
shared_ptr<T> <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr<U> const & r); // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
template<typename T, typename U>
|
2002-02-14 17:12:07 +00:00
|
|
|
shared_ptr<T> <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr<U> const & r);
|
2002-02-06 19:42:04 +00:00
|
|
|
template<typename T, typename U>
|
2002-02-14 17:12:07 +00:00
|
|
|
shared_ptr<T> <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr<U> const & r);
|
2002-02-06 19:42:04 +00:00
|
|
|
template<typename T, typename U>
|
2002-02-14 17:12:07 +00:00
|
|
|
shared_ptr<T> <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr<U> const & r); // never throws
|
2002-02-02 18:36:12 +00:00
|
|
|
|
|
|
|
}</pre>
|
2002-02-14 17:12:07 +00:00
|
|
|
<h2><a name="Members">Members</a></h2>
|
|
|
|
<h3><a name="element_type">element_type</a></h3>
|
|
|
|
<pre>typedef T element_type;</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p>Provides the type of the template parameter T.</p>
|
|
|
|
</blockquote>
|
|
|
|
<h3><a name="constructors">constructors</a></h3>
|
2002-02-15 13:31:58 +00:00
|
|
|
<pre>shared_ptr();</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Effects:</b> Constructs a <b>shared_ptr</b>.</p>
|
|
|
|
<p><b>Postconditions:</b> <A href="#use_count">use count</A> is 1; the stored
|
|
|
|
pointer is 0.</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>
|
|
|
|
<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>explicit shared_ptr(T * p);</pre>
|
2002-02-14 17:12:07 +00:00
|
|
|
<blockquote>
|
|
|
|
<p><b>Requirements:</b> The expression <code>delete p</code> must be well-formed
|
|
|
|
and must not invoke undefined behavior.
|
|
|
|
</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<typename D> shared_ptr(T * p, D d);</pre>
|
|
|
|
<blockquote>
|
|
|
|
<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
|
|
|
|
undefined behavior, and must not throw exceptions.
|
|
|
|
</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>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 & r); // never throws
|
|
|
|
template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws</pre>
|
|
|
|
<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> nothing.</p>
|
|
|
|
</blockquote>
|
2002-02-15 13:31:58 +00:00
|
|
|
<pre>explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const & r);</pre>
|
2002-02-14 17:12:07 +00:00
|
|
|
<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<typename Y> shared_ptr(std::auto_ptr<Y> & 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>
|
|
|
|
<pre>~shared_ptr(); // never throws</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<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>
|
|
|
|
<P><B>Postconditions:</B> <A href="#use_count">use count</A> for all remaining
|
|
|
|
copies is decreased by one.</P>
|
|
|
|
<P><B>Throws:</B> nothing.</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
|
|
|
|
deleted object's destructor does not throw exceptions. See the smart pointer <A href="smart_ptr.htm#Common requirements">
|
|
|
|
common requirements</A>.</P>
|
|
|
|
</BLOCKQUOTE>
|
|
|
|
<H3><a name="assignment">assignment</a></H3>
|
|
|
|
<pre>shared_ptr & operator=(shared_ptr const & r); // never throws
|
|
|
|
template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
|
|
|
|
template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
|
2002-02-15 13:31:58 +00:00
|
|
|
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied
|
|
|
|
guarantees) via different means, without creating a temporary. In particular,
|
|
|
|
in the example:</P>
|
|
|
|
<pre>
|
|
|
|
shared_ptr<int> p(new int);
|
|
|
|
shared_ptr<void> q(p);
|
|
|
|
p = p;
|
|
|
|
q = p;
|
|
|
|
</pre>
|
|
|
|
<p>both assignments may be no-ops.</p>
|
2002-02-14 17:12:07 +00:00
|
|
|
</BLOCKQUOTE>
|
|
|
|
<h3><a name="reset">reset</a></h3>
|
2002-02-15 13:31:58 +00:00
|
|
|
<pre>void reset();</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
|
|
|
|
</BLOCKQUOTE>
|
|
|
|
<pre>void reset(T * p);</pre>
|
2002-02-14 17:12:07 +00:00
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
|
2002-02-15 13:31:58 +00:00
|
|
|
<P><B>Notes:</B> Note the implied requirement that <b>T</b> is a complete type.</P>
|
2002-02-14 17:12:07 +00:00
|
|
|
</BLOCKQUOTE>
|
|
|
|
<pre>template<typename D> void reset(T * p, D d);</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
|
|
|
|
</BLOCKQUOTE>
|
|
|
|
<h3><a name="indirection">indirection</a></h3>
|
|
|
|
<pre>T & operator*() const; // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<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->() const; // never throws</pre>
|
|
|
|
<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>
|
|
|
|
<pre>T * get() const; // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Returns:</b> the stored pointer.</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>
|
|
|
|
<h3><a name="unique">unique</a></h3>
|
|
|
|
<pre>bool unique() const; // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
|
|
|
|
<p><b>Throws:</b> nothing.</p>
|
|
|
|
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>. <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="use_count">use_count</a></h3>
|
|
|
|
<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>
|
2002-02-15 14:46:53 +00:00
|
|
|
<h3><a name="conversions">conversions</a></h3>
|
|
|
|
<pre>operator <i>implementation-defined-type</i> () const; // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Returns:</b> an implementation defined value that, when used in boolean
|
|
|
|
contexts, is equivalent to <code>get() != 0</code>.</p>
|
|
|
|
<p><b>Throws:</b> nothing.</p>
|
|
|
|
<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be
|
|
|
|
used in boolean contexts, like <code>if (p && p->valid()) {}</code>. The
|
|
|
|
actual target type is typically a pointer to a member function, avloiding many
|
|
|
|
of the implicit conversion pitfalls.</P>
|
|
|
|
</blockquote>
|
2002-02-14 17:12:07 +00:00
|
|
|
<h3><a name="swap">swap</a></h3>
|
|
|
|
<pre>void swap(shared_ptr & b); // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
|
|
|
|
<p><b>Throws:</b> nothing.</p>
|
|
|
|
<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<typename T, typename U>
|
|
|
|
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
|
|
|
|
<p><b>Throws:</b> nothing.</p>
|
|
|
|
<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<typename T, typename U>
|
|
|
|
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
|
|
|
<blockquote>
|
|
|
|
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
|
|
|
|
<p><b>Throws:</b> nothing.</p>
|
|
|
|
<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<typename T>
|
2002-02-09 01:18:00 +00:00
|
|
|
bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws</pre>
|
2002-02-14 17:12:07 +00:00
|
|
|
<blockquote>
|
2002-03-08 16:56:16 +00:00
|
|
|
<p><b>Returns:</b> an implementation-defined value such that <b>operator<</b>
|
2002-02-14 17:12:07 +00:00
|
|
|
is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
|
|
|
of the C++ standard.</p>
|
|
|
|
<p><b>Throws:</b> nothing.</p>
|
|
|
|
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
|
|
|
|
associative containers. <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="free-swap">swap</a></h3>
|
|
|
|
<pre>template<typename T>
|
2002-02-02 18:36:12 +00:00
|
|
|
void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws</pre>
|
2002-02-14 17:12:07 +00:00
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
|
|
|
|
<P><B>Throws:</B> nothing.</P>
|
|
|
|
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
|
|
|
generic programming.</P>
|
|
|
|
</BLOCKQUOTE>
|
|
|
|
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
|
|
|
<pre>template<typename T, typename U>
|
|
|
|
shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><STRONG>Requires:</STRONG> The expression <code>static_cast<T*>(r.get())</code>
|
|
|
|
must be well-formed.</P>
|
|
|
|
<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy
|
|
|
|
of <code>static_cast<T*>(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<T>(static_cast<T*>(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>
|
|
|
|
<pre>template<typename T, typename U>
|
|
|
|
shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast<T*>(r.get())</CODE>
|
|
|
|
must be well-formed and its behavior defined.</P>
|
|
|
|
<P><B>Returns:</B></P>
|
|
|
|
<UL>
|
|
|
|
<LI>
|
|
|
|
When <CODE>dynamic_cast<T*>(r.get())</CODE> returns a nonzero
|
|
|
|
value, a <STRONG>shared_ptr<T></STRONG> object that stores a copy of
|
|
|
|
it and shares ownership with <STRONG>r</STRONG>;
|
|
|
|
<LI>
|
|
|
|
Otherwise, a default-constructed <STRONG>shared_ptr<T></STRONG> object.</LI></UL>
|
|
|
|
<P><B>Throws:</B> <STRONG>std::bad_alloc</STRONG>.</P>
|
2002-03-08 16:56:16 +00:00
|
|
|
<P><B>Exception safety:</B> If an exception is thrown, the function has no
|
2002-02-14 17:12:07 +00:00
|
|
|
effect.</P>
|
|
|
|
<P><B>Notes:</B> the seemingly equivalent expression</P>
|
|
|
|
<P><CODE>shared_ptr<T>(dynamic_cast<T*>(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>
|
|
|
|
<pre>template<typename T, typename U>
|
|
|
|
shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
|
2002-02-15 13:31:58 +00:00
|
|
|
polymorphic_cast</A><T*>(r.get())</CODE> must be well-formed and
|
|
|
|
its behavior defined.</p>
|
2002-02-14 17:12:07 +00:00
|
|
|
<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy
|
|
|
|
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_cast</A><T*>(r.get())</CODE>
|
|
|
|
and shares ownership with <B>r</B>.</P>
|
2002-02-15 14:46:53 +00:00
|
|
|
<P><B>Throws:</B> <STRONG>std::bad_cast</STRONG> when the pointer cannot be
|
|
|
|
converted.</P>
|
2002-02-14 17:12:07 +00:00
|
|
|
<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<typename T, typename U>
|
|
|
|
shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws</pre>
|
|
|
|
<BLOCKQUOTE>
|
|
|
|
<p><STRONG>Requires:</STRONG> The expression <CODE><A href="../conversion/cast.htm#Polymorphic_cast">
|
2002-02-15 13:31:58 +00:00
|
|
|
polymorphic_downcast</A><T*>(r.get())</CODE> must be well-formed
|
|
|
|
and its behavior defined.</p>
|
2002-02-14 17:12:07 +00:00
|
|
|
<P><B>Returns:</B> A <STRONG>shared_ptr<T></STRONG> object that stores a copy
|
|
|
|
of <CODE><A href="../conversion/cast.htm#Polymorphic_cast">polymorphic_downcast</A><T*>(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>
|
|
|
|
<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>
|
|
|
|
objects.</p>
|
|
|
|
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b>
|
|
|
|
objects will have a use count of 1 rather than a use count of 2, since the set
|
|
|
|
is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not
|
|
|
|
contain duplicate entries. Furthermore, the use count may be even higher at
|
|
|
|
various times while <b>push_back</b> and <b>insert</b> container operations are
|
|
|
|
performed. More complicated yet, the container operations may throw exceptions
|
|
|
|
under a variety of circumstances. Getting the memory management and exception
|
|
|
|
handling in this example right without a smart pointer would be a nightmare.</p>
|
|
|
|
<h2><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
|
|
|
|
pimpl) idiom which avoids exposing the body (implementation) in the header
|
|
|
|
file.</p>
|
|
|
|
<p>The <A href="shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A> sample
|
|
|
|
program includes a header file, <A href="shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
|
|
|
|
which uses a <b>shared_ptr<></b> to an incomplete type to hide the
|
|
|
|
implementation. The instantiation of member functions which require a complete
|
|
|
|
type occurs in the <A href="shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
|
|
|
|
implementation file. Note that there is no need for an explicit destructor.
|
|
|
|
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>
|
|
|
|
<P><B>Q.</B> There are several variations of shared pointers, with different
|
|
|
|
tradeoffs; why does the smart pointer library supply only a single
|
|
|
|
implementation? It would be useful to be able to experiment with each type so
|
|
|
|
as to find the most suitable for the job at hand?<BR>
|
|
|
|
<b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
|
|
|
|
standard shared-ownership pointer. Having a single pointer type is important
|
|
|
|
for stable library interfaces, since different shared pointers typically cannot
|
|
|
|
interoperate, i.e. a reference counted pointer (used by library A) cannot share
|
|
|
|
ownership with a linked pointer (used by library B.)</P>
|
|
|
|
<P><B>Q.</B> Why doesn't <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>
|
|
|
|
<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<int> a(new int);
|
2002-01-11 20:20:07 +00:00
|
|
|
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
|
|
|
|
|
|
|
|
int * p = a.release();
|
|
|
|
|
2002-02-14 17:12:07 +00:00
|
|
|
// 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>
|
|
|
|
<b>A.</b> Because (your pet feature here) would mandate a reference counted
|
|
|
|
implementation or a linked list implementation, or some other specific
|
|
|
|
implementation. This is not the intent.</p>
|
|
|
|
<hr>
|
|
|
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
|
|
|
|
14 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
|
|
|
|
distribute this document is granted provided this copyright notice appears in
|
|
|
|
all copies. This document is provided "as is" without express or implied
|
|
|
|
warranty, and with no claim as to its suitability for any purpose.</p>
|
|
|
|
</body>
|
2002-02-02 18:36:12 +00:00
|
|
|
</html>
|