forked from boostorg/smart_ptr
Revised to match the style of the C++ standard.
[SVN r12806]
This commit is contained in:
731
shared_ptr.htm
731
shared_ptr.htm
@ -1,376 +1,423 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>shared_ptr</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
<body text="#000000" bgColor="#ffffff">
|
||||
<h1><IMG height="86" alt="c++boost.gif (8819 bytes)" src="../../c++boost.gif" width="277" align="middle">shared_ptr
|
||||
class template</h1>
|
||||
<p><A href="#Introduction">Introduction</A><br>
|
||||
<A href="#Synopsis">Synopsis</A><br>
|
||||
<A href="#Members">Members</A><br>
|
||||
<A href="#functions">Free Functions</A><br>
|
||||
<A href="#example">Example</A><br>
|
||||
<A href="#Handle/Body">Handle/Body Idiom</A><br>
|
||||
<A href="#FAQ">Frequently Asked Questions</A><br>
|
||||
<A href="smarttests.htm">Smart Pointer Timings</A></p>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
|
||||
The object pointed to is guaranteed to be deleted when the last <b>shared_ptr</b>
|
||||
pointing to it is destroyed or reset. See the <A href="#example">example</A>.</p>
|
||||
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
|
||||
requirements of the C++ Standard Library, and so can be used in standard
|
||||
library containers. Comparison operators are supplied so that <b>shared_ptr</b>
|
||||
works with the standard library's associative containers.</p>
|
||||
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically
|
||||
allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for
|
||||
that usage.</p>
|
||||
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not
|
||||
work correctly with cyclic data structures. For example, if <b>main()</b> holds
|
||||
a <b>shared_ptr</b> to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b>
|
||||
back to <b>A</b>, <b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
|
||||
will leave <b>A</b> dangling with a use count of 1.</p>
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
|
||||
to. <b>T</b> must meet the smart pointer <A href="smart_ptr.htm#Common requirements">
|
||||
common requirements</A>. <b>T</b> may be <b>void</b>, but in that case,
|
||||
either an explicit delete function must be passed in, or the pointed-to object
|
||||
must have a trivial destructor.</p>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>shared_ptr</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_ptr class template</h1>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#functions">Free Functions</a><br>
|
||||
<a href="#example">Example</a><br>
|
||||
<a href="#Handle/Body">Handle/Body Idiom</a><br>
|
||||
<a href="#FAQ">Frequently Asked Questions</a><br>
|
||||
<a href="smarttests.htm">Smart Pointer Timings</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <b>new</b>
|
||||
expression.) The object pointed to is guaranteed to be deleted when
|
||||
the last <b>shared_ptr</b> pointing to it is destroyed or reset.
|
||||
See the <a href="#example">example</a>.</p>
|
||||
|
||||
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b>
|
||||
and <b>Assignable</b> requirements of the C++ Standard Library, and so
|
||||
can be used in standard library containers. Comparison operators
|
||||
are supplied so that <b>shared_ptr</b> works with
|
||||
the standard library's associative containers.</p>
|
||||
|
||||
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="shared_array.htm"><b>shared_array</b></a>
|
||||
for that usage.</p>
|
||||
|
||||
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not work
|
||||
correctly with cyclic data structures. For example, if <b>main()</b> holds a <b>shared_ptr</b>
|
||||
to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
|
||||
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
|
||||
will leave <b>A</b> dangling with a use count of 1.</p>
|
||||
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object
|
||||
pointed to. <b>T</b> must meet the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.
|
||||
<b>T</b> may be <b>void</b>, but in that case, either an explicit delete
|
||||
function must be passed in, or the pointed-to object must have a trivial destructor.</p>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>namespace boost {
|
||||
template<typename T> class <A href="weak_ptr.htm" >weak_ptr</A>;
|
||||
|
||||
template<typename T> class shared_ptr {
|
||||
|
||||
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);
|
||||
template<typename D> <a href="#constructors">shared_ptr</a>(T * p, D d);
|
||||
<a href="#destructor">~shared_ptr</a>(); // never throws
|
||||
explicit <A href="#constructors" >shared_ptr</A>(T * p = 0);
|
||||
template<typename D> <A href="#constructors" >shared_ptr</A>(T * p, D d);
|
||||
<A href="#destructor" >~shared_ptr</A>(); // never throws
|
||||
|
||||
<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
|
||||
template<typename Y> <a href="#constructors">shared_ptr</a>(std::auto_ptr<Y> & r);
|
||||
<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
|
||||
<A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A> const & r);
|
||||
template<typename Y> <A href="#constructors" >shared_ptr</A>(std::auto_ptr<Y> & r);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0);
|
||||
template<typename D> void <a href="#reset">reset</a>(T * p, D d);
|
||||
void <A href="#reset" >reset</A>(T * p = 0);
|
||||
template<typename D> void <A href="#reset" >reset</A>(T * p, D d);
|
||||
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
T & <A href="#indirection" >operator*</A>() const; // never throws
|
||||
T * <A href="#indirection" >operator-></A>() const; // never throws
|
||||
T * <A href="#get" >get</A>() const; // never throws
|
||||
|
||||
bool <a href="#unique">unique</a>() const; // never throws
|
||||
long <a href="#use_count">use_count</a>() const; // never throws
|
||||
bool <A href="#unique" >unique</A>() const; // never throws
|
||||
long <A href="#use_count" >use_count</A>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(shared_ptr<T> & b); // never throws
|
||||
void <A href="#swap" >swap</A>(shared_ptr<T> & b); // never throws
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
bool <a href="#comparison">operator==</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
bool <A href="#comparison" >operator==</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#comparison">operator!=</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
bool <A href="#comparison" >operator!=</A>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#comparison">operator<</a>(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
|
||||
bool <A href="#comparison" >operator<</A>(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||
template<typename T> void <A href="#free-swap" >swap</A>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
shared_ptr<T> <A href="#shared_static_cast" >shared_static_cast</A>(shared_ptr<U> const & r); // never throws
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr<U> const & r);
|
||||
shared_ptr<T> <A href="#shared_dynamic_cast" >shared_dynamic_cast</A>(shared_ptr<U> const & r);
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_polymorphic_cast">shared_polymorphic_cast</a>(shared_ptr<U> const & r);
|
||||
shared_ptr<T> <A href="#shared_polymorphic_cast" >shared_polymorphic_cast</A>(shared_ptr<U> const & r);
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_polymorphic_downcast">shared_polymorphic_downcast</a>(shared_ptr<U> const & r); // never throws
|
||||
shared_ptr<T> <A href="#shared_polymorphic_downcast" >shared_polymorphic_downcast</A>(shared_ptr<U> const & r); // never throws
|
||||
|
||||
}</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
|
||||
<pre>explicit shared_ptr(T * p = 0);</pre>
|
||||
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>, which
|
||||
must be a pointer to an object that was allocated via a C++ <b>new</b> expression or be 0.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">~shared_ptr</a>).
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>delete p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> 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>.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1.
|
||||
<b>D</b>'s copy constructor and destructor must not throw.
|
||||
When the the time comes to delete the object pointed to by <b>p</b>, the object
|
||||
<b>d</b> is used in the statement <b>d(p)</b>. Invoking the object <b>d</b> with
|
||||
parameter <b>p</b> in this way must not throw.
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
|
||||
<pre>shared_ptr(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr(std::auto_ptr<Y> & r);</pre>
|
||||
<p>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>
|
||||
for all copies is 1 more than the initial use count, or 1
|
||||
in the <b>auto_ptr</b> case. In the <b>auto_ptr</b> case, <b>r.release()</b>
|
||||
is called.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>,
|
||||
which may be thrown during construction from <b>auto_ptr</b>.
|
||||
If an exception is thrown, the constructor has no effect.</p>
|
||||
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
|
||||
<pre>~shared_ptr(); // never throws</pre>
|
||||
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
|
||||
deletes the object pointed to by the stored pointer.
|
||||
Note that <b>delete</b> on a pointer with a value of 0 is harmless.
|
||||
<b>T</b> need not be a complete type.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted object's destructor does not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="operator=">assignment</a></h3>
|
||||
|
||||
<pre>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);</pre>
|
||||
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>,
|
||||
which may be thrown during assignment from <b>auto_ptr</b>.
|
||||
If an exception is thrown, the assignment has no effect.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
|
||||
<pre>void reset(T * p = 0);</pre>
|
||||
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, <b>delete p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> void reset(T * p, D d);</pre>
|
||||
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
|
||||
<b>D</b>'s copy constructor must not throw.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.</p>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="unique">unique</a></h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<p>Returns true if no other <b>shared_ptr</b> is sharing ownership of
|
||||
the stored pointer, false otherwise.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>shared_ptr</b> that do not use an explicit reference
|
||||
count, it might be removed from some future version. Thus it should
|
||||
be used for debugging purposes only, and not production code.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T>
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<blockquote>
|
||||
<p>Provides the type of the template parameter T.</p>
|
||||
</blockquote>
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>explicit shared_ptr(T * p = 0);</pre>
|
||||
<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>
|
||||
<pre>shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const & r);</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> <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>
|
||||
</BLOCKQUOTE>
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(T * p = 0);</pre>
|
||||
<BLOCKQUOTE>
|
||||
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
|
||||
</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>
|
||||
<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>
|
||||
bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>shared_ptr</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>.
|
||||
The implementation uses <b>std::less<T *></b> to perform the
|
||||
comparison. This ensures that the comparison is handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but <b>std::less<></b> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).</p>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> An implementation-defined value such that <code>operator<</code>
|
||||
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>
|
||||
void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<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>
|
||||
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>shared_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer.</p>
|
||||
<p>Note that the seemingly equivalent expression</p>
|
||||
<blockquote><code>shared_ptr<T>(static_cast<T*>(r.get()))</code></blockquote>
|
||||
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p>
|
||||
|
||||
<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>
|
||||
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>shared_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer unless the result of the
|
||||
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the
|
||||
construction of the new <b>shared_ptr</b> if the result of the cast is 0. If an exception is thrown, the
|
||||
cast has no effect.</p>
|
||||
<p>Note that the seemingly equivalent expression</p>
|
||||
<blockquote><code>shared_ptr<T>(dynamic_cast<T*>(r.get()))</code></blockquote>
|
||||
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p>
|
||||
|
||||
<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>
|
||||
<p>Perform a <a href="../conversion/cast.htm#Polymorphic_cast"><b>polymorphic_cast</b><a> on the stored pointer,
|
||||
returning another <b>shared_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer.
|
||||
The only exception which may be thrown is <b>std::bad_cast</b>, if the pointer type can not be converted.
|
||||
If an exception is thrown, the cast has no effect.</p>
|
||||
|
||||
<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>
|
||||
<p>Perform a <a href="../conversion/cast.htm#Polymorphic_cast"><b>polymorphic_downcast</b><a> on the stored pointer,
|
||||
returning another <b>shared_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer.</p>
|
||||
|
||||
<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> 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> 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.</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);
|
||||
<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>
|
||||
<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><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">
|
||||
polymorphic_cast</A><T*>(r.get())</CODE> must be well-formed and
|
||||
its behavior defined.</p>
|
||||
<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>
|
||||
<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>
|
||||
<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">
|
||||
polymorphic_downcast</A><T*>(r.get())</CODE> must be well-formed
|
||||
and its behavior defined.</p>
|
||||
<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);
|
||||
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
|
||||
|
||||
int * p = a.release();
|
||||
|
||||
// Who owns p now? b will still call delete on it in its destructor.</pre></blockquote>
|
||||
|
||||
<p><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 -->8 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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>
|
||||
|
||||
// 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>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user