forked from boostorg/smart_ptr
Best practices section, thread safety section, design notes added.
[SVN r14572]
This commit is contained in:
181
shared_ptr.htm
181
shared_ptr.htm
@ -8,11 +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="#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="#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>
|
||||||
@ -44,6 +46,43 @@
|
|||||||
to <STRONG>shared_ptr<T const></STRONG>, to <STRONG>shared_ptr<U></STRONG>
|
to <STRONG>shared_ptr<T const></STRONG>, to <STRONG>shared_ptr<U></STRONG>
|
||||||
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
|
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
|
||||||
shared_ptr<void></STRONG>.</P>
|
shared_ptr<void></STRONG>.</P>
|
||||||
|
<h2><a name="BestPractices">Best Practices</a></h2>
|
||||||
|
<P>A simple guideline that nearly eliminates the possibility of memory leaks
|
||||||
|
is: always use a named smart pointer variable to hold the result of <STRONG>new. </STRONG>
|
||||||
|
Every occurence of the <STRONG>new</STRONG> keyword in the code should have the
|
||||||
|
form:</P>
|
||||||
|
<PRE>shared_ptr<T> p(new Y);</PRE>
|
||||||
|
<P>It is, of course, acceptable to use another smart pointer in place of <STRONG>shared_ptr</STRONG>
|
||||||
|
above; having <STRONG>T</STRONG> and <STRONG>Y</STRONG> be the same type, or
|
||||||
|
passing arguments to <STRONG>Y</STRONG>'s constructor is also OK.</P>
|
||||||
|
<P>If you observe this guideline, it naturally follows that you will have no
|
||||||
|
explicit <STRONG>delete</STRONG>s; <STRONG>try/catch</STRONG> constructs will
|
||||||
|
be rare.</P>
|
||||||
|
<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to
|
||||||
|
see why this is dangerous, consider this example:</P>
|
||||||
|
<PRE>
|
||||||
|
void f(shared_ptr<int>, int);
|
||||||
|
int g();
|
||||||
|
|
||||||
|
void ok()
|
||||||
|
{
|
||||||
|
shared_ptr<int> p(new int(2));
|
||||||
|
f(p, g());
|
||||||
|
}
|
||||||
|
|
||||||
|
void bad()
|
||||||
|
{
|
||||||
|
f(shared_ptr<int>(new int(2)), g());
|
||||||
|
}
|
||||||
|
</PRE>
|
||||||
|
<P>The function <STRONG>ok</STRONG> follows the guideline to the letter, whereas <STRONG>
|
||||||
|
bad</STRONG> constructs the temporary <STRONG>shared_ptr</STRONG> in place,
|
||||||
|
admitting the possibility of a memory leak. Since function arguments are
|
||||||
|
evaluated in unspecified order, it is possible for <STRONG>new int(2)</STRONG> to
|
||||||
|
be evaluated first, <STRONG>g()</STRONG> second, and we may never get to the <STRONG>
|
||||||
|
shared_ptr </STRONG>constructor if <STRONG>g</STRONG> throws an exception.
|
||||||
|
See <A href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</A> of
|
||||||
|
the issue for more information.</P>
|
||||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||||
<pre>namespace boost {
|
<pre>namespace boost {
|
||||||
|
|
||||||
@ -122,6 +161,22 @@
|
|||||||
<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>[The poscondition of use_count() == 1 is too strong. Having the nothrow
|
||||||
|
guarantee is important, since <STRONG>reset()</STRONG> is specified in terms of
|
||||||
|
the default constructor, but the current specification requires that a count be
|
||||||
|
allocated. Therefore, this postcondition will be dropped in a future release.
|
||||||
|
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
|
||||||
|
default-constructed <STRONG>shared_ptr</STRONG>s. The second option is
|
||||||
|
difficult to achieve in the current header-only reference implementation due to
|
||||||
|
thread safety issues and initialization order, but it should not be precluded
|
||||||
|
by the specification.</EM></P>
|
||||||
|
<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
|
||||||
|
whether this constructor should be left implicit, enabling <STRONG>0</STRONG> to
|
||||||
|
be used as a shorthand for <STRONG>shared_ptr<T>().</STRONG>]</EM></P>
|
||||||
<pre>template<typename Y> explicit shared_ptr(Y * p);</pre>
|
<pre>template<typename Y> explicit shared_ptr(Y * p);</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
|
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
|
||||||
@ -138,6 +193,10 @@
|
|||||||
use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG>
|
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>
|
on a pointer that has a value of 0 is harmless.</P>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
<P><EM>[This constructor has been changed to a template in order to remember the actual
|
||||||
|
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
|
||||||
|
not have a virtual destructor, or is <STRONG>void</STRONG>.]</EM></P>
|
||||||
<pre>template<typename Y, typename D> shared_ptr(Y * p, D d);</pre>
|
<pre>template<typename Y, typename D> shared_ptr(Y * p, D d);</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. The copy
|
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. The copy
|
||||||
@ -152,6 +211,14 @@
|
|||||||
<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>,
|
||||||
<code>d(p)</code> is invoked.</p>
|
<code>d(p)</code> is invoked.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
<P><EM>[Custom deallocators allow a factory function returning a <STRONG>shared_ptr</STRONG>
|
||||||
|
to insulate the user from its memory allocation strategy. Since the deallocator
|
||||||
|
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
|
||||||
|
example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG>
|
||||||
|
to a statically allocated object.</EM></P>
|
||||||
|
<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>
|
||||||
<pre>shared_ptr(shared_ptr const & r); // never throws
|
<pre>shared_ptr(shared_ptr const & r); // never throws
|
||||||
template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws</pre>
|
template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -161,6 +228,8 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev
|
|||||||
increased by one.</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>
|
||||||
|
is being copied.]</EM></P>
|
||||||
<pre>explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const & r);</pre>
|
<pre>explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A> const & 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> Constructs a <b>shared_ptr</b>, as if by storing a copy of the
|
||||||
@ -171,6 +240,17 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev
|
|||||||
<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 is an optional part of the specification; it depends on the
|
||||||
|
existence of <STRONG>weak_ptr</STRONG>. It is true that <STRONG>weak_ptr</STRONG>
|
||||||
|
support imposes overhead on every <STRONG>shared_ptr</STRONG> user, regardless
|
||||||
|
of whether weak pointers are used.</EM></P>
|
||||||
|
<P><EM>On the other hand, cyclic references are a serious problem with all reference
|
||||||
|
counted designs. Not providing a solution within the library is unacceptable;
|
||||||
|
if users are forced to reinvent the weak pointer wheel, there is substantial
|
||||||
|
probability that they will get it wrong, as designing a safe <STRONG>weak_ptr</STRONG>
|
||||||
|
interface is non-trivial.</EM></P>
|
||||||
|
<P><EM>My opinion is that the added functionality is worth the cost. <STRONG>weak_ptr</STRONG>
|
||||||
|
is provided in the reference implementation as a proof of concept.]</EM></P>
|
||||||
<pre>template<typename Y> shared_ptr(std::auto_ptr<Y> & r);</pre>
|
<pre>template<typename Y> shared_ptr(std::auto_ptr<Y> & 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>
|
||||||
@ -180,6 +260,9 @@ template<typename Y> shared_ptr(shared_ptr<Y> const & r); // nev
|
|||||||
<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
|
||||||
|
not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is
|
||||||
|
by design, as the constructor offers the strong guarantee.]</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>
|
||||||
@ -211,6 +294,8 @@ q = p;
|
|||||||
<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<typename Y> void reset(Y * p);</pre>
|
<pre>template<typename Y> 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>
|
||||||
@ -243,8 +328,12 @@ q = p;
|
|||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
|
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
|
||||||
<p><b>Throws:</b> nothing.</p>
|
<p><b>Throws:</b> nothing.</p>
|
||||||
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.</P>
|
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.
|
||||||
|
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>
|
||||||
</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>
|
||||||
@ -255,16 +344,19 @@ q = p;
|
|||||||
for debugging and testing purposes, not for production code.</P>
|
for debugging and testing purposes, not for production code.</P>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<h3><a name="conversions">conversions</a></h3>
|
<h3><a name="conversions">conversions</a></h3>
|
||||||
<pre>operator <i>implementation-defined-type</i> () const; // never throws</pre>
|
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Returns:</b> an implementation defined value that, when used in boolean
|
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts,
|
||||||
contexts, is equivalent to <code>get() != 0</code>.</p>
|
is equivalent to <code>get() != 0</code>.</p>
|
||||||
<p><b>Throws:</b> nothing.</p>
|
<p><b>Throws:</b> nothing.</p>
|
||||||
<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be
|
<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>.
|
used in boolean contexts, like <code>if (p && p->valid()) {}</code>.
|
||||||
The actual target type is typically a pointer to a member function, avloiding
|
The actual target type is typically a pointer to a member function, avoiding
|
||||||
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
|
||||||
|
to be declared in conditions when using <STRONG>shared_dynamic_cast </STRONG>or <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 & b); // never throws</pre>
|
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
@ -288,13 +380,19 @@ q = p;
|
|||||||
<pre>template<typename T>
|
<pre>template<typename T>
|
||||||
bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws</pre>
|
bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws</pre>
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<p><b>Returns:</b> an implementation-defined value such that <b>operator<</b> is
|
<p><b>Returns:</b> an unspecified value such that <b>operator<</b> is a
|
||||||
a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
|
||||||
of the C++ standard.</p>
|
of the C++ standard.</p>
|
||||||
<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>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
<P><EM>[<STRONG>Operator<</STRONG> has been preferred over a <STRONG>std::less </STRONG>
|
||||||
|
specialization for consistency and legality reasons, as <STRONG>std::less</STRONG>
|
||||||
|
is required to return the results of <STRONG>operator<</STRONG>, and many
|
||||||
|
standard algorithms use <STRONG>operator<</STRONG> instead of <STRONG>std::less</STRONG>
|
||||||
|
for comparisons when a predicate is not supplied.</EM></P>
|
||||||
|
<P><EM>The rest of the comparison operators are omitted by design.]</EM></P>
|
||||||
<h3><a name="free-swap">swap</a></h3>
|
<h3><a name="free-swap">swap</a></h3>
|
||||||
<pre>template<typename T>
|
<pre>template<typename T>
|
||||||
void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws</pre>
|
void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws</pre>
|
||||||
@ -304,6 +402,9 @@ q = p;
|
|||||||
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
|
||||||
generic programming.</P>
|
generic programming.</P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
<P><EM>[<STRONG>swap</STRONG> is defined in the same namespace as <STRONG>shared_ptr</STRONG>
|
||||||
|
as this is currently the only legal way to supply a <STRONG>swap</STRONG> function
|
||||||
|
that has a chance to be used by the standard library.]</EM></P>
|
||||||
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
||||||
<pre>template<typename T, typename U>
|
<pre>template<typename T, typename U>
|
||||||
shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws</pre>
|
shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws</pre>
|
||||||
@ -389,6 +490,65 @@ q = p;
|
|||||||
implementation file. Note that there is no need for an explicit destructor.
|
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
|
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete
|
||||||
type.</p>
|
type.</p>
|
||||||
|
<h2><a name="ThreadSafety">Thread Safety</a></h2>
|
||||||
|
<p><STRONG>shared_ptr</STRONG> objects offer the same level of thread safety as
|
||||||
|
built-in types. A <STRONG>shared_ptr</STRONG> instance can be "read"
|
||||||
|
(accessed using only const operations) simultaneously by multiple threads.
|
||||||
|
Different <STRONG>shared_ptr</STRONG> instances can be "written to" (accessed
|
||||||
|
using mutable operations such as <STRONG>operator= </STRONG>or <STRONG>reset</STRONG>)
|
||||||
|
simultaneosly by multiple threads (even when these instances are copies, and
|
||||||
|
share the same reference count underneath.)</p>
|
||||||
|
<P>Any other simultaneous accesses result in undefined behavior.</P>
|
||||||
|
<P>Examples:</P>
|
||||||
|
<pre>
|
||||||
|
shared_ptr<int> p(new int(42));
|
||||||
|
|
||||||
|
//--- Example 1 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
shared_ptr<int> p2(p); // reads p
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
shared_ptr<int> p3(p); // OK, multiple reads are safe
|
||||||
|
|
||||||
|
//--- Example 2 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
|
||||||
|
p.reset(new int(1912)); // writes p
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
p2.reset(); // OK, writes p2
|
||||||
|
|
||||||
|
//--- Example 3 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p = p3; // reads p3, writes p
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
p3.reset(); // writes p3; undefined, simultaneous read/write
|
||||||
|
|
||||||
|
//--- Example 4 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p3 = p2; // reads p2, writes p3
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
// p2 goes out of scope: undefined, the destructor is considered a "write access"
|
||||||
|
|
||||||
|
//--- Example 5 ---
|
||||||
|
|
||||||
|
// thread A
|
||||||
|
p3.reset(new int(1));
|
||||||
|
|
||||||
|
// thread B
|
||||||
|
p3.reset(new int(2)); // undefined, multiple writes
|
||||||
|
</pre>
|
||||||
|
<p><STRONG>shared_ptr</STRONG> uses <A href="../config/config.htm">Boost.Config</A>
|
||||||
|
to detect whether the implementation supports threads. If your program is
|
||||||
|
single-threaded, but your platform is autodetected by <STRONG>Boost.Config</STRONG>
|
||||||
|
as supporting multiple threads, <STRONG>#define BOOST_DISABLE_THREADS</STRONG> to
|
||||||
|
eliminate the thread safety overhead.</p>
|
||||||
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
|
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
|
||||||
<P><B>Q.</B> There are several variations of shared pointers, with different
|
<P><B>Q.</B> There are several variations of shared pointers, with different
|
||||||
tradeoffs; why does the smart pointer library supply only a single
|
tradeoffs; why does the smart pointer library supply only a single
|
||||||
@ -408,8 +568,8 @@ q = p;
|
|||||||
pointer of choice for a wide range of applications. (Those interested in policy
|
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">
|
based smart pointers should read <A href="http://cseng.aw.com/book/0,,0201704315,00.html">
|
||||||
Modern C++ Design</A> by Andrei Alexandrescu.)</P>
|
Modern C++ Design</A> by Andrei Alexandrescu.)</P>
|
||||||
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate to
|
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate
|
||||||
hide the complexity. Again, why not policies?<BR>
|
to hide the complexity. Again, why not policies?<BR>
|
||||||
<B>A.</B> Template parameters affect the type. See the answer to the first
|
<B>A.</B> Template parameters affect the type. See the answer to the first
|
||||||
question above.</P>
|
question above.</P>
|
||||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
|
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
|
||||||
@ -445,8 +605,7 @@ 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 <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->23 July 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||||
04 May 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
|
||||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||||
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
|
Copyright 2002 Peter Dimov. Permission to copy, use, modify, sell and
|
||||||
distribute this document is granted provided this copyright notice appears in
|
distribute this document is granted provided this copyright notice appears in
|
||||||
|
Reference in New Issue
Block a user