mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-10-04 19:51:02 +02:00
Compare commits
25 Commits
boost-1.18
...
boost-1.26
Author | SHA1 | Date | |
---|---|---|---|
|
e14ed052f9 | ||
|
1a9b1dd123 | ||
|
a93dfc1837 | ||
|
c5846378ab | ||
|
aea7d0c9c8 | ||
|
65c3f2dc85 | ||
|
5fbc553611 | ||
|
c41b060618 | ||
|
c17921c417 | ||
|
94287044ba | ||
|
7c09884eac | ||
|
a90a157ea6 | ||
|
ac8d0f5505 | ||
|
8f23f07740 | ||
|
3b183163c9 | ||
|
55a377b446 | ||
|
2d342f0ddf | ||
|
060ea4a573 | ||
|
6a12efb77b | ||
|
e57d3f4bc1 | ||
|
16902b1f4f | ||
|
cb1b1b7cc0 | ||
|
26fe4c4078 | ||
|
4e832788bf | ||
|
db43d160b4 |
@@ -9,6 +9,13 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 6 Jul 01 Reorder shared_ptr code so VC++ 6 member templates work, allowing
|
||||
// polymorphic pointers to now work with that compiler (Gary Powell)
|
||||
// 21 May 01 Require complete type where incomplete type is unsafe.
|
||||
// (suggested by Vladimir Prus)
|
||||
// 21 May 01 operator= fails if operand transitively owned by *this, as in a
|
||||
// linked list (report by Ken Johnson, fix by Beman Dawes)
|
||||
// 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams)
|
||||
// 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
|
||||
// 24 Jul 00 Change throw() to // never throws. See lib guidelines
|
||||
// Exception-specification rationale. (Beman Dawes)
|
||||
@@ -51,8 +58,14 @@
|
||||
#include <cstddef> // for std::size_t
|
||||
#include <memory> // for std::auto_ptr
|
||||
#include <algorithm> // for std::swap
|
||||
#include <boost/utility.hpp> // for boost::noncopyable
|
||||
#include <boost/utility.hpp> // for boost::noncopyable, checked_delete, checked_array_delete
|
||||
#include <functional> // for std::less
|
||||
#include <boost/static_assert.hpp> // for BOOST_STATIC_ASSERT
|
||||
|
||||
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
@@ -71,9 +84,8 @@ template<typename T> class scoped_ptr : noncopyable {
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws
|
||||
~scoped_ptr() { delete ptr; }
|
||||
|
||||
void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } }
|
||||
~scoped_ptr() { checked_delete(ptr); }
|
||||
void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } }
|
||||
T& operator*() const { return *ptr; } // never throws
|
||||
T* operator->() const { return ptr; } // never throws
|
||||
T* get() const { return ptr; } // never throws
|
||||
@@ -97,9 +109,10 @@ template<typename T> class scoped_array : noncopyable {
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws
|
||||
~scoped_array() { delete [] ptr; }
|
||||
~scoped_array() { checked_array_delete(ptr); }
|
||||
|
||||
void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} }
|
||||
void reset( T* p=0 ) { if ( ptr != p )
|
||||
{checked_array_delete(ptr); ptr=p;} }
|
||||
|
||||
T* get() const { return ptr; } // never throws
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
@@ -122,29 +135,23 @@ template<typename T> class shared_ptr {
|
||||
|
||||
explicit shared_ptr(T* p =0) : px(p) {
|
||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
||||
catch (...) { delete p; throw; }
|
||||
catch (...) { checked_delete(p); throw; }
|
||||
}
|
||||
|
||||
shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
|
||||
|
||||
~shared_ptr() { dispose(); }
|
||||
|
||||
shared_ptr& operator=(const shared_ptr& r) {
|
||||
share(r.px,r.pn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES )
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) || defined (BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
template<typename Y>
|
||||
shared_ptr(const shared_ptr<Y>& r) : px(r.px) { // never throws
|
||||
++*(pn = r.pn);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
template<typename Y>
|
||||
explicit shared_ptr(std::auto_ptr<Y>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r) {
|
||||
@@ -152,27 +159,11 @@ template<typename T> class shared_ptr {
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(std::auto_ptr<Y>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { delete px; }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
pn = tmp;
|
||||
} // allocate new reference counter
|
||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
explicit shared_ptr(std::auto_ptr<T>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
|
||||
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { delete px; }
|
||||
if (*pn == 1) { checked_delete(px); }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
@@ -182,15 +173,44 @@ template<typename T> class shared_ptr {
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
explicit shared_ptr(std::auto_ptr<T>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
|
||||
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { checked_delete(px); }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
pn = tmp;
|
||||
} // allocate new reference counter
|
||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The assignment operator and the copy constructor must come after
|
||||
// the templated versions for MSVC6 to work. (Gary Powell)
|
||||
shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
|
||||
|
||||
shared_ptr& operator=(const shared_ptr& r) {
|
||||
share(r.px,r.pn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(T* p=0) {
|
||||
if ( px == p ) return; // fix: self-assignment safe
|
||||
if (--*pn == 0) { delete px; }
|
||||
if (--*pn == 0) { checked_delete(px); }
|
||||
else { // allocate new reference counter
|
||||
try { pn = new long; } // fix: prevent leak if new throws
|
||||
catch (...) {
|
||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
||||
delete p;
|
||||
checked_delete(p);
|
||||
throw;
|
||||
} // catch
|
||||
} // allocate new reference counter
|
||||
@@ -215,7 +235,7 @@ template<typename T> class shared_ptr {
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends. (Matthew Langston)
|
||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
private:
|
||||
#endif
|
||||
|
||||
@@ -227,13 +247,15 @@ template<typename T> class shared_ptr {
|
||||
template<typename Y> friend class shared_ptr;
|
||||
#endif
|
||||
|
||||
void dispose() { if (--*pn == 0) { delete px; delete pn; } }
|
||||
void dispose() { if (--*pn == 0) { checked_delete(px); delete pn; } }
|
||||
|
||||
void share(T* rpx, long* rpn) {
|
||||
if (pn != rpn) {
|
||||
if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0
|
||||
++*rpn; // done before dispose() in case rpn transitively
|
||||
// dependent on *this (bug reported by Ken Johnson)
|
||||
dispose();
|
||||
px = rpx;
|
||||
++*(pn = rpn);
|
||||
pn = rpn;
|
||||
}
|
||||
} // share
|
||||
}; // shared_ptr
|
||||
@@ -258,7 +280,7 @@ template<typename T> class shared_array {
|
||||
|
||||
explicit shared_array(T* p =0) : px(p) {
|
||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
||||
catch (...) { delete [] p; throw; }
|
||||
catch (...) { checked_array_delete(p); throw; }
|
||||
}
|
||||
|
||||
shared_array(const shared_array& r) : px(r.px) // never throws
|
||||
@@ -267,22 +289,24 @@ template<typename T> class shared_array {
|
||||
~shared_array() { dispose(); }
|
||||
|
||||
shared_array& operator=(const shared_array& r) {
|
||||
if (pn != r.pn) {
|
||||
if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0
|
||||
++*r.pn; // done before dispose() in case r.pn transitively
|
||||
// dependent on *this (bug reported by Ken Johnson)
|
||||
dispose();
|
||||
px = r.px;
|
||||
++*(pn = r.pn);
|
||||
pn = r.pn;
|
||||
}
|
||||
return *this;
|
||||
} // operator=
|
||||
|
||||
void reset(T* p=0) {
|
||||
if ( px == p ) return; // fix: self-assignment safe
|
||||
if (--*pn == 0) { delete [] px; }
|
||||
if (--*pn == 0) { checked_array_delete(px); }
|
||||
else { // allocate new reference counter
|
||||
try { pn = new long; } // fix: prevent leak if new throws
|
||||
catch (...) {
|
||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
||||
delete [] p;
|
||||
checked_array_delete(p);
|
||||
throw;
|
||||
} // catch
|
||||
} // allocate new reference counter
|
||||
@@ -309,7 +333,7 @@ template<typename T> class shared_array {
|
||||
T* px; // contained pointer
|
||||
long* pn; // ptr to reference counter
|
||||
|
||||
void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
|
||||
void dispose() { if (--*pn == 0) { checked_array_delete(px); delete pn; } }
|
||||
|
||||
}; // shared_array
|
||||
|
||||
@@ -369,5 +393,10 @@ template<typename T>
|
||||
|
||||
#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_SMART_PTR_HPP
|
||||
|
||||
|
||||
|
@@ -13,8 +13,8 @@
|
||||
<tr>
|
||||
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
|
||||
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home</big></font></a></td>
|
||||
<td><a href="../../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries</big></font></a></td>
|
||||
<td><a href="../../people.htm"><font face="Arial" color="#FFFFFF"><big>People</big></font></a></td>
|
||||
<td><a href="../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries</big></font></a></td>
|
||||
<td><a href="../../people/people.htm"><font face="Arial" color="#FFFFFF"><big>People</big></font></a></td>
|
||||
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ</big></font></a></td>
|
||||
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More</big></font></a></td>
|
||||
</tr>
|
||||
@@ -27,11 +27,10 @@ expressions.
|
||||
<li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
|
||||
<li>Header <a href="../../boost/smart_ptr.hpp">smart_ptr.hpp</a></li>
|
||||
<li>Test program <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.</li>
|
||||
<li>Download <a href="../../boost_all.zip">all of Boost</a> (ZIP format).</li>
|
||||
<li>Submitted by <a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/beman_dawes.html">Beman
|
||||
Dawes</a>.</li>
|
||||
</ul>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->02 Aug 2000<!--webbot bot="Timestamp" endspan i-checksum="14748" -->
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->14 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14885" -->
|
||||
</p>
|
||||
|
||||
</body>
|
||||
|
@@ -15,21 +15,26 @@ allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>ne
|
||||
expression.) The array pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <strong>scoped_array</strong>, or via an explicit <strong>scoped_array::reset()</strong>.</p>
|
||||
<p>Class<strong> scoped_array</strong> is a simple solution for simple
|
||||
needs. It cannot be used in C++ Standard Library containers. See <a href="shared_array.htm"><strong>shared_array</strong></a>
|
||||
needs. It supplies a basic "resource acquisition is
|
||||
initialization" facility, without shared-ownership or transfer-of-ownership
|
||||
semantics. Both its name and enforcement of semantics (by being <a href="../utility/utility.htm#class noncopyable">noncopyable</a>)
|
||||
signal its intent to retain ownership solely within the current scope. By
|
||||
being <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is
|
||||
safer than <b>shared_array</b> for pointers which should not be copied.</p>
|
||||
<p>Because <strong>scoped_array</strong> is so simple, in its usual
|
||||
implementation every operation is as fast as a built-in array pointer and it has no
|
||||
more space overhead that a built-in array pointer.</p>
|
||||
<p>It cannot be used in C++ Standard Library containers. See <a href="shared_array.htm"><strong>shared_array</strong></a>
|
||||
if <strong>scoped_array</strong> does not meet your needs.</p>
|
||||
<p>Class<strong> scoped_array</strong> cannot correctly hold a pointer to a
|
||||
single object. See <a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a>
|
||||
for that usage.</p>
|
||||
<p>Because <strong>scoped_array</strong> is so simple, in its usual
|
||||
implementation every operation is as fast as a built-in array pointer and has no
|
||||
more space overhead that a built-in array pointer.</p>
|
||||
<p>A heavier duty alternative to a <strong>scoped_array</strong> is a <strong>scoped_ptr</strong>
|
||||
to a C++ Standard Library <strong>vector</strong>.</p>
|
||||
<p>A C++ Standard Library <strong>vector</strong> is a <strong> </strong>heavier duty alternative to a <strong>scoped_array</strong>.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2>Class scoped_array Synopsis</h2>
|
||||
<pre>#include <boost/smart_ptr.hpp>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
|
||||
@@ -54,6 +59,8 @@ template<typename T> class scoped_array : <a href="../utility/utility.htm#
|
||||
<pre>explicit scoped_array( T* p=0 ); // never throws</pre>
|
||||
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
|
||||
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
|
||||
<pre>~scoped_array();</pre>
|
||||
<p>Deletes the array pointed to by the stored pointer. Note that in C++ <tt>delete</tt>[]
|
||||
@@ -74,11 +81,16 @@ or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
|
||||
in the array.</p>
|
||||
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
|
||||
<pre>T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the stored pointer.</p>
|
||||
<h2>Class <a name="shared_array_example">scoped_array example</a></h2>
|
||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||
<hr>
|
||||
<p>Revised December 8, 1999</p>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
|
||||
-->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964"
|
||||
-->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. 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"
|
||||
|
@@ -16,19 +16,29 @@ expression.) The object pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <strong>scoped_ptr</strong>, or via an explicit <strong>scoped_ptr::reset()</strong>.
|
||||
See <a href="#scoped_ptr_example">example</a>.</p>
|
||||
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
|
||||
needs. It cannot be used in C++ Standard Library containers. See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
|
||||
needs. It supplies a basic "resource acquisition is
|
||||
initialization" facility, without shared-ownership or transfer-of-ownership
|
||||
semantics. Both its name and enforcement of semantics (by being <a href="../utility/utility.htm#class noncopyable">noncopyable</a>)
|
||||
signal its intent to retain ownership solely within the current scope.
|
||||
Because it is <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is
|
||||
safer than <b>shared_ptr</b> or <b> std::auto_ptr</b> for pointers which should not be
|
||||
copied.</p>
|
||||
<p>Because <strong>scoped_ptr</strong> is so simple, in its usual implementation
|
||||
every operation is as fast as for a built-in pointer and it has no more space overhead
|
||||
that a built-in pointer. (Because of the "complete type"
|
||||
requirement for delete and reset members, they may have one additional function
|
||||
call overhead in certain idioms. See <a href="#Handle/Body">Handle/Body
|
||||
Idiom</a>.) </p>
|
||||
<p>Class<strong> scoped_ptr</strong> cannot be used in C++ Standard Library containers. See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
|
||||
or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p>
|
||||
<p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="scoped_array.htm"><strong>scoped_array</strong></a>
|
||||
for that usage.</p>
|
||||
<p>Because <strong>scoped_ptr</strong> is so simple, in its usual implementation
|
||||
every operation is as fast as a built-in pointer and has no more space overhead
|
||||
that a built-in pointer.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2>Class scoped_ptr Synopsis</h2>
|
||||
<pre>#include <boost/smart_ptr.hpp>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
|
||||
@@ -52,8 +62,10 @@ template<typename T> class scoped_ptr : <a href="../utility/utility.htm#cl
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
|
||||
<pre>explicit scoped_ptr( T* p=0 ); // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must
|
||||
have been allocated via a C++ <tt>new</tt> expression or be 0..</p>
|
||||
have been allocated via a C++ <tt>new</tt> expression or be 0.</p>
|
||||
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
|
||||
<pre>~scoped_ptr();</pre>
|
||||
<p>Deletes the object pointed to by the stored pointer. Note that in C++, <tt>delete</tt>
|
||||
@@ -71,6 +83,7 @@ C++ <tt>new</tt> expression or be 0.</p>
|
||||
<h3>scoped_ptr <a name="scoped_ptr_operator->">operator-></a> and <a name="scoped_ptr_get">get</a></h3>
|
||||
<pre>T* operator->() const; // never throws
|
||||
T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is not required by get() be a complete type. See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Both return the stored pointer.</p>
|
||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
|
||||
<pre>#include <iostream>
|
||||
@@ -98,25 +111,37 @@ output:</p>
|
||||
2
|
||||
Buckle my shoe</pre>
|
||||
</blockquote>
|
||||
<h2>Handle/Body Idiom</h2>
|
||||
<p>One common usage of <b>shared_pointer</b> is to implement a handle/body
|
||||
structure which avoids exposing the body (implementation) in the header file:</p>
|
||||
<pre>class handle
|
||||
{
|
||||
public: // simple forwarding functions to the body class
|
||||
void f();
|
||||
void g(int);
|
||||
private:
|
||||
friend class body; //incomplete class hides implementation
|
||||
boost::scoped_ptr<body> imp;
|
||||
};</pre>
|
||||
<p>This code requires that <code>class body</code> have a trivial destructor to
|
||||
avoid undefined behavior. This is because the definition of <code>class
|
||||
body</code> is not visible at the time scoped_ptr<> deletes it. See ISO
|
||||
5.3.5/5. Note that some compilers will issue a warning even though the
|
||||
above code is well defined.</p>
|
||||
<h2>Rationale</h2>
|
||||
<p>The primary reason to use <b> scoped_ptr</b> rather than <b> auto_ptr</b> is to let readers
|
||||
of your code know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer
|
||||
ownership.</p>
|
||||
<p>A secondary reason to use <b> scoped_ptr</b> is to prevent a later maintenance programmer from adding a function that actually transfers
|
||||
ownership by returning the <b> auto_ptr</b> (because the maintenance programmer saw
|
||||
<b>auto_ptr</b>, and assumed ownership could safely be transferred.) </p>
|
||||
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b> bool</b> is usually
|
||||
just an <b>int</b>. Indeed, some argued against including <b> bool</b> in the
|
||||
C++ standard because of that. But by coding <b> bool</b> rather than <b> int</b>, you tell your readers
|
||||
what your intent is. Same with <b> scoped_ptr</b> - you are signaling intent.</p>
|
||||
<p>It has been suggested that <b>boost::scoped_ptr<T></b> is equivalent to
|
||||
<b>std::auto_ptr<T> const</b>. Ed Brey pointed out, however, that
|
||||
reset() will not work on a <b>std::auto_ptr<T> const.</b></p>
|
||||
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
|
||||
<p>One common usage of <b>scoped_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="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
|
||||
sample program includes a header file, <a href="scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
|
||||
which uses a <b>scoped_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="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
|
||||
implementation file.</p>
|
||||
<h2>FAQ</h2>
|
||||
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
|
||||
<b>A</b>. Because the whole point of <b>scoped_ptr</b> is to signal intent not
|
||||
to transfer ownership. Use <b>std::auto_ptr</b> if ownership transfer is
|
||||
required.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 July 2000<!--webbot bot="Timestamp" endspan i-checksum="18764" --></p>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110" --></p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. 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"
|
||||
|
16
scoped_ptr_example.cpp
Normal file
16
scoped_ptr_example.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Boost scoped_ptr_example implementation file -----------------------------//
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
|
||||
void example::do_something() { std::cout << "did something\n"; }
|
||||
|
||||
example::~example() {}
|
21
scoped_ptr_example.hpp
Normal file
21
scoped_ptr_example.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Boost scoped_ptr_example header file ------------------------------------//
|
||||
|
||||
#include <boost/smart_ptr.hpp>
|
||||
|
||||
// The point of this example is to prove that even though
|
||||
// example::implementation is an incomplete type in translation units using
|
||||
// this header, scoped_ptr< implementation > is still valid because the type
|
||||
// is complete where it counts - in the inplementation translation unit where
|
||||
// destruction is actually instantiated.
|
||||
|
||||
class example : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
example();
|
||||
~example();
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::scoped_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
10
scoped_ptr_example_test.cpp
Normal file
10
scoped_ptr_example_test.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// Boost scoped_ptr_example_test main program -------------------------------//
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example my_example;
|
||||
my_example.do_something();
|
||||
return 0;
|
||||
}
|
@@ -23,20 +23,20 @@ shared_array</strong> works by default for Standard Library's Associative
|
||||
Container Compare template parameter. For compilers not supporting partial
|
||||
specialization, the user must explicitly pass the less<> functor.</p>
|
||||
<p>Class<strong> shared_array</strong> cannot correctly hold a pointer to a
|
||||
single object. See <a href="shared_ptr.htm"><strong>shared_array</strong></a>
|
||||
single object. See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
|
||||
for that usage.</p>
|
||||
<p>Class<strong> shared_array</strong> will not work correctly with cyclic data
|
||||
structures. For example, if main() holds a shared_array pointing to array A,
|
||||
which directly or indirectly holds a shared_array pointing back to array A, then
|
||||
array A's use_count() will be 2, and destruction of the main() shared_array will
|
||||
leave array A dangling with a use_count() of 1.</p>
|
||||
<p>A heavier duty alternative to a <strong>shared_array</strong> is a <strong>shared_ptr</strong>
|
||||
to a C++ Standard Library <strong>vector</strong>.</p>
|
||||
<p>A C++ Standard Library <strong>vector</strong> is <strong> </strong>a <strong>
|
||||
</strong>heavier duty alternative to a <strong>shared_array</strong>.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
||||
requirements</a>.</p>
|
||||
<h2>Class shared_array Synopsis</h2>
|
||||
<pre>#include <boost/smart_ptr.hpp>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class shared_array {
|
||||
@@ -154,21 +154,30 @@ or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
|
||||
in the array.</p>
|
||||
<h3>shared_array <a name="shared_array_get">get</a></h3>
|
||||
<pre>T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the stored pointer.</p>
|
||||
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
|
||||
<p><tt>long use_count() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
|
||||
stored pointer.</p>
|
||||
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
|
||||
<p><tt>bool unique() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
|
||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
||||
<h2>Class <a name="shared_array_example">shared_array example</a></h2>
|
||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||
<hr>
|
||||
<p>Revised December 8, 1999</p>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964" -->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. 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"
|
||||
|
@@ -10,6 +10,14 @@
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
||||
<a name="shared_ptr">shared_ptr</a></h1>
|
||||
<p><a href="#Introduction">Introduction<br>
|
||||
Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#shared_ptr_example">Example</a><br>
|
||||
<a href="#Handle/Body">Handle/Body Idiom</a><br>
|
||||
<a href="smarttests.htm">Frequently Asked Questions<br>
|
||||
Smart Pointer Timings</a></p>
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>Class <strong>shared_ptr</strong> stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
|
||||
expression.) The object pointed to is guaranteed to be deleted when
|
||||
@@ -33,8 +41,8 @@ object A dangling with a use_count() of 1.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
||||
requirements</a>.</p>
|
||||
<h2>Class shared_ptr Synopsis</h2>
|
||||
<pre>#include <boost/smart_ptr.hpp>
|
||||
<h2>Class shared_ptr <a name="Synopsis"> Synopsis</a></h2>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class shared_ptr {
|
||||
@@ -112,7 +120,7 @@ than supplying a full range of comparison operators (<, >, <=, >=).<
|
||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
|
||||
<p>The current implementation does not supply the member template functions if
|
||||
the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
|
||||
<h2>Class shared_ptr Members</h2>
|
||||
<h2>Class shared_ptr <a name="Members"> Members</a></h2>
|
||||
<h3>shared_ptr <a name="shared_ptr_element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
@@ -180,21 +188,76 @@ an exception is thrown, <tt>delete p</tt> is called.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_operator->">operator-></a> and <a name="shared_ptr_get">get</a></h3>
|
||||
<pre>T* operator->() const; // never throws
|
||||
T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is not required by get() to be a complete type . See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Both return the stored pointer.</p>
|
||||
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
|
||||
<p><tt>long use_count() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
|
||||
stored pointer.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
|
||||
<p><tt>bool unique() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
|
||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
||||
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
|
||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||
<p>See <a href="shared_ptr_example.cpp"> shared_ptr_example.cpp</a> for a complete example program.</p>
|
||||
<p>This program builds a std::vector and std::set of FooPtr's.</p>
|
||||
<p>Note that after the two containers have been populated, some of the FooPtr objects
|
||||
will have use_count()==1 rather than use_count()==2, since foo_set is a std::set
|
||||
rather than a std::multiset, and thus does not contain duplicate entries. Furthermore, use_count() may be even higher
|
||||
at various times while push_back() and insert() container operations are performed.
|
||||
More complicated yet, the container operations may throw exceptions under a
|
||||
variety of circumstances. Without using a smart pointer, memory and
|
||||
exception management 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.</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. <b>Shared_ptr</b> is
|
||||
carefully crafted to meet common needs without extensive parameterization.
|
||||
Someday 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 don't <b>shared_ptr</b> (and 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 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 (your pet feature here)?<br>
|
||||
<b>A.</b> Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent.
|
||||
[Provided by Peter Dimov]<br>
|
||||
</p>
|
||||
<hr>
|
||||
<p>Revised December 8, 1999</p>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 July, 2001<!--webbot bot="Timestamp" endspan i-checksum="21067" -->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. 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"
|
||||
|
96
shared_ptr_example.cpp
Normal file
96
shared_ptr_example.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Boost shared_ptr_example.cpp --------------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 2001. Permission to copy,
|
||||
// use, modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided "as is"
|
||||
// without express or implied warranty, and with no claim as to its
|
||||
// suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 Initial complete version (Beman Dawes)
|
||||
|
||||
// The original code for this example appeared in the shared_ptr documentation.
|
||||
// Ray Gallimore pointed out that foo_set was missing a Compare template
|
||||
// argument, so would not work as intended. At that point the code was
|
||||
// turned into an actual .cpp file so it could be compiled and tested.
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
|
||||
// The application will produce a series of
|
||||
// objects of type Foo which later must be
|
||||
// accessed both by occurrence (std::vector)
|
||||
// and by ordering relationship (std::set).
|
||||
|
||||
struct Foo
|
||||
{
|
||||
Foo( int _x ) : x(_x) {}
|
||||
~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
|
||||
int x;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Foo> FooPtr;
|
||||
|
||||
struct FooPtrOps
|
||||
{
|
||||
bool operator()( const FooPtr & a, const FooPtr & b )
|
||||
{ return a->x > b->x; }
|
||||
void operator()( const FooPtr & a )
|
||||
{ std::cout << a->x << "\n"; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<FooPtr> foo_vector;
|
||||
std::set<FooPtr,FooPtrOps> foo_set; // NOT multiset!
|
||||
|
||||
FooPtr foo_ptr( new Foo( 2 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset( new Foo( 1 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset( new Foo( 3 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset ( new Foo( 2 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
std::cout << "foo_vector:\n";
|
||||
std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
|
||||
|
||||
std::cout << "\nfoo_set:\n";
|
||||
std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
|
||||
std::cout << "\n";
|
||||
|
||||
// Expected output:
|
||||
//
|
||||
// foo_vector:
|
||||
// 2
|
||||
// 1
|
||||
// 3
|
||||
// 2
|
||||
//
|
||||
// foo_set:
|
||||
// 3
|
||||
// 2
|
||||
// 1
|
||||
//
|
||||
// Destructing a Foo with x=2
|
||||
// Destructing a Foo with x=1
|
||||
// Destructing a Foo with x=3
|
||||
// Destructing a Foo with x=2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
21
shared_ptr_example2.cpp
Normal file
21
shared_ptr_example2.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// Boost shared_ptr_example2 implementation file -----------------------------//
|
||||
|
||||
#include "shared_ptr_example2.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
example::example( const example & s ) : _imp( s._imp ) {}
|
||||
|
||||
example & example::operator=( const example & s )
|
||||
{ _imp = s._imp; return *this; }
|
||||
|
||||
void example::do_something()
|
||||
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; }
|
||||
|
||||
example::~example() {}
|
27
shared_ptr_example2.hpp
Normal file
27
shared_ptr_example2.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
// Boost shared_ptr_example2 header file -----------------------------------//
|
||||
|
||||
#include <boost/smart_ptr.hpp>
|
||||
|
||||
// This example demonstrates the handle/body idiom (also called pimpl and
|
||||
// several other names). It separates the interface (in this header file)
|
||||
// from the implementation (in shared_ptr_example2.cpp).
|
||||
|
||||
// Note that even though example::implementation is an incomplete type in
|
||||
// some translation units using this header, shared_ptr< implementation >
|
||||
// is still valid because the type is complete where it counts - in the
|
||||
// shared_ptr_example2.cpp translation unit where functions requiring a
|
||||
// complete type are actually instantiated.
|
||||
|
||||
class example
|
||||
{
|
||||
public:
|
||||
example();
|
||||
~example();
|
||||
example( const example & );
|
||||
example & operator=( const example & );
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::shared_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
15
shared_ptr_example2_test.cpp
Normal file
15
shared_ptr_example2_test.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// Boost shared_ptr_example2_test main program ------------------------------//
|
||||
|
||||
#include "shared_ptr_example2.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example a;
|
||||
a.do_something();
|
||||
example b(a);
|
||||
b.do_something();
|
||||
example c;
|
||||
c = a;
|
||||
c.do_something();
|
||||
return 0;
|
||||
}
|
@@ -27,11 +27,11 @@ provides four smart pointer template classes:</p>
|
||||
<tr>
|
||||
<td>
|
||||
<p align="left"><a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a></td>
|
||||
<td>Simple sole ownership of single objects.</td>
|
||||
<td>Simple sole ownership of single objects. Noncopyable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="scoped_array.htm"><strong>scoped_array</strong></a></td>
|
||||
<td>Simple sole ownership of arrays.</td>
|
||||
<td>Simple sole ownership of arrays. Noncopyable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="shared_ptr.htm"><strong>shared_ptr</strong></a></td>
|
||||
@@ -53,10 +53,23 @@ provided to verify correct operation.</p>
|
||||
<p>A page on <a href="smarttests.htm">Smart Pointer Timings</a> will be of
|
||||
interest to those curious about performance issues.</p>
|
||||
<h2><a name="Common requirements">Common requirements</a></h2>
|
||||
<p>These smart pointer classes have a template parameter, <tt>T</tt>, which
|
||||
<p>These smart pointer classes have a template parameter, <tt><b>T</b></tt>, which
|
||||
specifies the type of the object pointed to by the smart pointer. The
|
||||
behavior of all four classes is undefined if the destructor or operator delete
|
||||
for objects of type <tt>T</tt> throws exceptions.</p>
|
||||
for objects of type <tt><b>T</b></tt> throw exceptions.</p>
|
||||
<p><code><b>T</b></code> may be an incomplete type at the point of smart pointer
|
||||
declaration. Unless otherwise specified, it is required that <code><b>T</b></code>
|
||||
be a complete type at points of smart pointer instantiation. Implementations are
|
||||
required to diagnose (treat as an error) all violations of this requirement,
|
||||
including deletion of an incomplete type. See <a href="../utility/utility.htm#checked_delete">checked_delete()</a>.</p>
|
||||
<h3>Rationale</h3>
|
||||
<p>The requirements on <tt><b>T</b></tt> are carefully crafted to maximize safety
|
||||
yet allow handle-body (also called pimpl) and similar idioms. In these idioms a
|
||||
smart pointer may appear in translation units where <tt><b>T</b></tt> is an
|
||||
incomplete type. This separates interface from implementation and hides
|
||||
implementation from translation units which merely use the interface.
|
||||
Examples described in the documentation for specific smart pointers illustrate
|
||||
use of smart pointers in these idioms.</p>
|
||||
<h2>Exception safety</h2>
|
||||
<p>Several functions in these smart pointer classes are specified as having
|
||||
"no effect" or "no effect except such-and-such" if an
|
||||
@@ -78,6 +91,10 @@ never throws</kbd>. </p>
|
||||
<p>Functions which destroy objects of the pointed to type are prohibited from
|
||||
throwing exceptions by the <a href="#Common requirements">Common requirements</a>.</p>
|
||||
<h2>History and acknowledgements</h2>
|
||||
<p>May, 2001. Vladimir Prus suggested requiring a complete type on
|
||||
destruction. Refinement evolved in discussions including Dave Abrahams,
|
||||
Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus,
|
||||
Shankar Sai, and others.</p>
|
||||
<p>November, 1999. Darin Adler provided operator ==, operator !=, and std::swap
|
||||
and std::less specializations for shared types.</p>
|
||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
|
||||
@@ -125,7 +142,7 @@ implementation.</p>
|
||||
<p>See the Revision History section of the header for further contributors.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
|
||||
-->24 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14986"
|
||||
-->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110"
|
||||
--></p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
|
@@ -6,20 +6,26 @@
|
||||
// implied warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// Revision History
|
||||
// 24 May 01 use Boost test library for error detection, reporting, add tests
|
||||
// for operations on incomplete types (Beman Dawes)
|
||||
// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
|
||||
// 25 Sep 99 added swap tests
|
||||
// 20 Jul 99 header name changed to .hpp
|
||||
// 20 Apr 99 additional error tests added.
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
#ifdef NDEBUG
|
||||
#error This test program makes no sense if NDEBUG is defined
|
||||
#endif
|
||||
class Incomplete;
|
||||
|
||||
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
|
||||
{
|
||||
return incomplete.get();
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
using boost::scoped_ptr;
|
||||
@@ -28,7 +34,7 @@ using boost::shared_ptr;
|
||||
using boost::shared_array;
|
||||
|
||||
template<typename T>
|
||||
void ck( const T* v1, T v2 ) { assert( *v1 == v2 ); }
|
||||
void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); }
|
||||
|
||||
namespace {
|
||||
int UDT_use_count; // independent of pointer maintained counts
|
||||
@@ -48,169 +54,189 @@ class UDT {
|
||||
void value( long v ) { value_ = v;; }
|
||||
}; // UDT
|
||||
|
||||
// tests on incomplete types -----------------------------------------------//
|
||||
|
||||
// Certain smart pointer operations are specified to work on incomplete types,
|
||||
// and some uses depend upon this feature. These tests verify compilation
|
||||
// only - the functions aren't actually invoked.
|
||||
|
||||
class Incomplete;
|
||||
|
||||
Incomplete * check_incomplete( scoped_ptr<Incomplete>& incomplete )
|
||||
{
|
||||
return incomplete.get();
|
||||
}
|
||||
|
||||
Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
|
||||
shared_ptr<Incomplete>& i2 )
|
||||
{
|
||||
incomplete.swap(i2);
|
||||
cout << incomplete.use_count() << " " << incomplete.unique() << endl;
|
||||
return incomplete.get();
|
||||
}
|
||||
// main --------------------------------------------------------------------//
|
||||
|
||||
// This isn't a very systematic test; it just hits some of the basics.
|
||||
|
||||
int main() {
|
||||
int test_main( int, char ** ) {
|
||||
|
||||
assert( UDT_use_count == 0 ); // reality check
|
||||
BOOST_TEST( UDT_use_count == 0 ); // reality check
|
||||
|
||||
// test scoped_ptr with a built-in type
|
||||
long * lp = new long;
|
||||
scoped_ptr<long> sp ( lp );
|
||||
assert( sp.get() == lp );
|
||||
assert( lp == sp.get() );
|
||||
assert( &*sp == lp );
|
||||
BOOST_TEST( sp.get() == lp );
|
||||
BOOST_TEST( lp == sp.get() );
|
||||
BOOST_TEST( &*sp == lp );
|
||||
|
||||
*sp = 1234568901L;
|
||||
assert( *sp == 1234568901L );
|
||||
assert( *lp == 1234568901L );
|
||||
BOOST_TEST( *sp == 1234568901L );
|
||||
BOOST_TEST( *lp == 1234568901L );
|
||||
ck( static_cast<long*>(sp.get()), 1234568901L );
|
||||
ck( lp, *sp );
|
||||
|
||||
sp.reset();
|
||||
assert( sp.get() == 0 );
|
||||
BOOST_TEST( sp.get() == 0 );
|
||||
|
||||
// test scoped_ptr with a user defined type
|
||||
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
|
||||
assert( udt_sp->value() == 999888777 );
|
||||
BOOST_TEST( udt_sp->value() == 999888777 );
|
||||
udt_sp.reset();
|
||||
udt_sp.reset( new UDT( 111222333 ) );
|
||||
assert( udt_sp->value() == 111222333 );
|
||||
BOOST_TEST( udt_sp->value() == 111222333 );
|
||||
udt_sp.reset( new UDT( 333222111 ) );
|
||||
assert( udt_sp->value() == 333222111 );
|
||||
BOOST_TEST( udt_sp->value() == 333222111 );
|
||||
|
||||
// test scoped_array with a build-in type
|
||||
char * sap = new char [ 100 ];
|
||||
scoped_array<char> sa ( sap );
|
||||
assert( sa.get() == sap );
|
||||
assert( sap == sa.get() );
|
||||
BOOST_TEST( sa.get() == sap );
|
||||
BOOST_TEST( sap == sa.get() );
|
||||
|
||||
strcpy( sa.get(), "Hot Dog with mustard and relish" );
|
||||
assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
|
||||
assert( sa[0] == 'H' );
|
||||
assert( sa[30] == 'h' );
|
||||
BOOST_TEST( sa[0] == 'H' );
|
||||
BOOST_TEST( sa[30] == 'h' );
|
||||
|
||||
sa[0] = 'N';
|
||||
sa[4] = 'd';
|
||||
assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
|
||||
|
||||
sa.reset();
|
||||
assert( sa.get() == 0 );
|
||||
BOOST_TEST( sa.get() == 0 );
|
||||
|
||||
// test shared_ptr with a built-in type
|
||||
int * ip = new int;
|
||||
shared_ptr<int> cp ( ip );
|
||||
assert( ip == cp.get() );
|
||||
assert( cp.use_count() == 1 );
|
||||
BOOST_TEST( ip == cp.get() );
|
||||
BOOST_TEST( cp.use_count() == 1 );
|
||||
|
||||
*cp = 54321;
|
||||
assert( *cp == 54321 );
|
||||
assert( *ip == 54321 );
|
||||
BOOST_TEST( *cp == 54321 );
|
||||
BOOST_TEST( *ip == 54321 );
|
||||
ck( static_cast<int*>(cp.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp );
|
||||
|
||||
shared_ptr<int> cp2 ( cp );
|
||||
assert( ip == cp2.get() );
|
||||
assert( cp.use_count() == 2 );
|
||||
assert( cp2.use_count() == 2 );
|
||||
BOOST_TEST( ip == cp2.get() );
|
||||
BOOST_TEST( cp.use_count() == 2 );
|
||||
BOOST_TEST( cp2.use_count() == 2 );
|
||||
|
||||
assert( *cp == 54321 );
|
||||
assert( *cp2 == 54321 );
|
||||
BOOST_TEST( *cp == 54321 );
|
||||
BOOST_TEST( *cp2 == 54321 );
|
||||
ck( static_cast<int*>(cp2.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp2 );
|
||||
|
||||
shared_ptr<int> cp3 ( cp );
|
||||
assert( cp.use_count() == 3 );
|
||||
assert( cp2.use_count() == 3 );
|
||||
assert( cp3.use_count() == 3 );
|
||||
BOOST_TEST( cp.use_count() == 3 );
|
||||
BOOST_TEST( cp2.use_count() == 3 );
|
||||
BOOST_TEST( cp3.use_count() == 3 );
|
||||
cp.reset();
|
||||
assert( cp2.use_count() == 2 );
|
||||
assert( cp3.use_count() == 2 );
|
||||
assert( cp.use_count() == 1 );
|
||||
BOOST_TEST( cp2.use_count() == 2 );
|
||||
BOOST_TEST( cp3.use_count() == 2 );
|
||||
BOOST_TEST( cp.use_count() == 1 );
|
||||
cp.reset( new int );
|
||||
*cp = 98765;
|
||||
assert( *cp == 98765 );
|
||||
BOOST_TEST( *cp == 98765 );
|
||||
*cp3 = 87654;
|
||||
assert( *cp3 == 87654 );
|
||||
assert( *cp2 == 87654 );
|
||||
BOOST_TEST( *cp3 == 87654 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
cp.swap( cp3 );
|
||||
assert( *cp == 87654 );
|
||||
assert( *cp2 == 87654 );
|
||||
assert( *cp3 == 98765 );
|
||||
BOOST_TEST( *cp == 87654 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
BOOST_TEST( *cp3 == 98765 );
|
||||
cp.swap( cp3 );
|
||||
assert( *cp == 98765 );
|
||||
assert( *cp2 == 87654 );
|
||||
assert( *cp3 == 87654 );
|
||||
BOOST_TEST( *cp == 98765 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
BOOST_TEST( *cp3 == 87654 );
|
||||
cp2 = cp2;
|
||||
assert( cp2.use_count() == 2 );
|
||||
assert( *cp2 == 87654 );
|
||||
BOOST_TEST( cp2.use_count() == 2 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
cp = cp2;
|
||||
assert( cp2.use_count() == 3 );
|
||||
assert( *cp2 == 87654 );
|
||||
assert( cp.use_count() == 3 );
|
||||
assert( *cp == 87654 );
|
||||
BOOST_TEST( cp2.use_count() == 3 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
BOOST_TEST( cp.use_count() == 3 );
|
||||
BOOST_TEST( *cp == 87654 );
|
||||
|
||||
shared_ptr<int> cp4;
|
||||
swap( cp2, cp4 );
|
||||
assert( cp4.use_count() == 3 );
|
||||
assert( *cp4 == 87654 );
|
||||
assert( cp2.get() == 0 );
|
||||
BOOST_TEST( cp4.use_count() == 3 );
|
||||
BOOST_TEST( *cp4 == 87654 );
|
||||
BOOST_TEST( cp2.get() == 0 );
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
set< shared_ptr<int> > scp;
|
||||
scp.insert(cp4);
|
||||
assert( scp.find(cp4) != scp.end() );
|
||||
assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
||||
BOOST_TEST( scp.find(cp4) != scp.end() );
|
||||
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
||||
#endif
|
||||
|
||||
// test shared_array with a built-in type
|
||||
char * cap = new char [ 100 ];
|
||||
shared_array<char> ca ( cap );
|
||||
assert( ca.get() == cap );
|
||||
assert( cap == ca.get() );
|
||||
assert( &ca[0] == cap );
|
||||
BOOST_TEST( ca.get() == cap );
|
||||
BOOST_TEST( cap == ca.get() );
|
||||
BOOST_TEST( &ca[0] == cap );
|
||||
|
||||
strcpy( ca.get(), "Hot Dog with mustard and relish" );
|
||||
assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
|
||||
assert( ca[0] == 'H' );
|
||||
assert( ca[30] == 'h' );
|
||||
BOOST_TEST( ca[0] == 'H' );
|
||||
BOOST_TEST( ca[30] == 'h' );
|
||||
|
||||
shared_array<char> ca2 ( ca );
|
||||
shared_array<char> ca3 ( ca2 );
|
||||
|
||||
ca[0] = 'N';
|
||||
ca[4] = 'd';
|
||||
assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( ca.use_count() == 3 );
|
||||
assert( ca2.use_count() == 3 );
|
||||
assert( ca3.use_count() == 3 );
|
||||
BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( ca.use_count() == 3 );
|
||||
BOOST_TEST( ca2.use_count() == 3 );
|
||||
BOOST_TEST( ca3.use_count() == 3 );
|
||||
ca2.reset();
|
||||
assert( ca.use_count() == 2 );
|
||||
assert( ca3.use_count() == 2 );
|
||||
assert( ca2.use_count() == 1 );
|
||||
BOOST_TEST( ca.use_count() == 2 );
|
||||
BOOST_TEST( ca3.use_count() == 2 );
|
||||
BOOST_TEST( ca2.use_count() == 1 );
|
||||
|
||||
ca.reset();
|
||||
assert( ca.get() == 0 );
|
||||
BOOST_TEST( ca.get() == 0 );
|
||||
|
||||
shared_array<char> ca4;
|
||||
swap( ca3, ca4 );
|
||||
assert( ca4.use_count() == 1 );
|
||||
assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
assert( ca3.get() == 0 );
|
||||
BOOST_TEST( ca4.use_count() == 1 );
|
||||
BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( ca3.get() == 0 );
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
set< shared_array<char> > sca;
|
||||
sca.insert(ca4);
|
||||
assert( sca.find(ca4) != sca.end() );
|
||||
assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
||||
BOOST_TEST( sca.find(ca4) != sca.end() );
|
||||
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
||||
#endif
|
||||
|
||||
// test shared_array with user defined type
|
||||
@@ -221,38 +247,38 @@ int main() {
|
||||
udta[2].value( 333 );
|
||||
shared_array<UDT> udta2 ( udta );
|
||||
|
||||
assert( udta[0].value() == 111 );
|
||||
assert( udta[1].value() == 222 );
|
||||
assert( udta[2].value() == 333 );
|
||||
assert( udta2[0].value() == 111 );
|
||||
assert( udta2[1].value() == 222 );
|
||||
assert( udta2[2].value() == 333 );
|
||||
BOOST_TEST( udta[0].value() == 111 );
|
||||
BOOST_TEST( udta[1].value() == 222 );
|
||||
BOOST_TEST( udta[2].value() == 333 );
|
||||
BOOST_TEST( udta2[0].value() == 111 );
|
||||
BOOST_TEST( udta2[1].value() == 222 );
|
||||
BOOST_TEST( udta2[2].value() == 333 );
|
||||
udta2.reset();
|
||||
assert( udta2.get() == 0 );
|
||||
assert( udta.use_count() == 1 );
|
||||
assert( udta2.use_count() == 1 );
|
||||
BOOST_TEST( udta2.get() == 0 );
|
||||
BOOST_TEST( udta.use_count() == 1 );
|
||||
BOOST_TEST( udta2.use_count() == 1 );
|
||||
|
||||
assert( UDT_use_count == 4 ); // reality check
|
||||
BOOST_TEST( UDT_use_count == 4 ); // reality check
|
||||
|
||||
// test shared_ptr with a user defined type
|
||||
UDT * up = new UDT;
|
||||
shared_ptr<UDT> sup ( up );
|
||||
assert( up == sup.get() );
|
||||
assert( sup.use_count() == 1 );
|
||||
BOOST_TEST( up == sup.get() );
|
||||
BOOST_TEST( sup.use_count() == 1 );
|
||||
|
||||
sup->value( 54321 ) ;
|
||||
assert( sup->value() == 54321 );
|
||||
assert( up->value() == 54321 );
|
||||
BOOST_TEST( sup->value() == 54321 );
|
||||
BOOST_TEST( up->value() == 54321 );
|
||||
|
||||
shared_ptr<UDT> sup2;
|
||||
sup2 = sup;
|
||||
assert( sup2->value() == 54321 );
|
||||
assert( sup.use_count() == 2 );
|
||||
assert( sup2.use_count() == 2 );
|
||||
BOOST_TEST( sup2->value() == 54321 );
|
||||
BOOST_TEST( sup.use_count() == 2 );
|
||||
BOOST_TEST( sup2.use_count() == 2 );
|
||||
sup2 = sup2;
|
||||
assert( sup2->value() == 54321 );
|
||||
assert( sup.use_count() == 2 );
|
||||
assert( sup2.use_count() == 2 );
|
||||
BOOST_TEST( sup2->value() == 54321 );
|
||||
BOOST_TEST( sup.use_count() == 2 );
|
||||
BOOST_TEST( sup2.use_count() == 2 );
|
||||
|
||||
cout << "OK" << endl;
|
||||
|
||||
|
@@ -530,7 +530,7 @@ Pointers Timings </h1>
|
||||
spreads its information as in the case of linked pointer.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->21 Feb 2000<!--webbot bot="Timestamp" endspan i-checksum="14372" -->
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
|
||||
and distribute this document is granted provided this copyright notice appears in all
|
||||
|
Reference in New Issue
Block a user