Compare commits

...

21 Commits

Author SHA1 Message Date
nobody
c80ea6fef7 This commit was manufactured by cvs2svn to create tag
'Version_1_23_0'.

[SVN r10562]
2001-07-06 20:31:02 +00:00
Beman Dawes
5fbc553611 Reorder shared_ptr code so VC++ 6 member templates work, allowing polymorphic pointers to now work with that compiler (Gary Powell)
[SVN r10548]
2001-07-06 13:23:07 +00:00
Beman Dawes
c41b060618 Initial checkin
[SVN r10221]
2001-05-24 18:43:24 +00:00
Beman Dawes
c17921c417 Documentation and example program improvements
[SVN r10220]
2001-05-24 18:42:25 +00:00
Beman Dawes
94287044ba Oops! Fix boo boo from prior fix
[SVN r10206]
2001-05-24 01:32:07 +00:00
Beman Dawes
7c09884eac Move MS VC++ pragmas to workaround compiler crash reported by several people with SP4 and SP5.
[SVN r10204]
2001-05-23 20:14:15 +00:00
Beman Dawes
a90a157ea6 Smart pointer and utility changes related to adding checked_delere and checked_array_delete
[SVN r10189]
2001-05-22 18:58:21 +00:00
Beman Dawes
ac8d0f5505 Fix doc errors, add shared_ptr_example program
[SVN r10165]
2001-05-21 14:58:07 +00:00
Beman Dawes
8f23f07740 Fix transitive dependency bug
[SVN r10164]
2001-05-21 14:56:51 +00:00
Beman Dawes
3b183163c9 Clarify rationale for noncopyability
[SVN r10085]
2001-05-10 16:00:49 +00:00
Beman Dawes
55a377b446 Change all eGroups references to YahooGroups
[SVN r9979]
2001-04-25 00:24:50 +00:00
Beman Dawes
2d342f0ddf Comment corrected (thanks to Joe Gottman)
[SVN r9582]
2001-03-19 12:34:12 +00:00
Beman Dawes
060ea4a573 Add a couple of comments to cut down on FAQ's
[SVN r9581]
2001-03-18 22:25:51 +00:00
Beman Dawes
6a12efb77b 1.21.1 run up, including new download instructions and fix broken hyperlinks
[SVN r9557]
2001-03-14 15:11:55 +00:00
Beman Dawes
e57d3f4bc1 Fix revision date
[SVN r9069]
2001-02-10 12:47:02 +00:00
Beman Dawes
16902b1f4f Add example
[SVN r9054]
2001-02-09 14:39:43 +00:00
Dave Abrahams
cb1b1b7cc0 Suppress some useless warnings with MSVC
[SVN r8704]
2001-01-22 04:53:38 +00:00
Beman Dawes
26fe4c4078 Fix typo shared_array should have read shared_ptr in one place (Ed Brey)
[SVN r8392]
2000-12-06 14:46:44 +00:00
John Maddock
4e832788bf Fix for egcs 1.1.1 problems with std::auto_ptr
[SVN r8225]
2000-11-16 11:17:22 +00:00
Beman Dawes
db43d160b4 libraries.htm and people.htm moved to sub-directories to make root directory cleaner.
[SVN r8166]
2000-11-10 15:39:05 +00:00
Beman Dawes
1412e40490 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
[SVN r8012]
2000-10-19 21:16:46 +00:00
16 changed files with 560 additions and 199 deletions

View File

@@ -9,6 +9,14 @@
// 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)
// 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
@@ -50,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 {
@@ -70,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
@@ -96,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
@@ -121,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>
shared_ptr(std::auto_ptr<Y>& r) {
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) {
@@ -151,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
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
@@ -181,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
@@ -214,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
@@ -226,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
@@ -257,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
@@ -266,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
@@ -308,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
@@ -368,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

View File

@@ -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>

View File

@@ -15,21 +15,26 @@ allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>ne
expression.)&nbsp;&nbsp; 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.&nbsp; It cannot be used in C++ Standard Library containers.&nbsp; See <a href="shared_array.htm"><strong>shared_array</strong></a>
needs.&nbsp;It supplies a basic &quot;resource acquisition is
initialization&quot; facility, without shared-ownership or transfer-of-ownership
semantics.&nbsp; 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.&nbsp; 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.&nbsp; 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.&nbsp; 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.&nbsp;&nbsp; <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 &lt;boost/smart_ptr.hpp&gt;
<pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost {
template&lt;typename T&gt; class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
@@ -54,6 +59,8 @@ template&lt;typename T&gt; 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.&nbsp;
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.&nbsp; 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.&nbsp;
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&nbsp; December 8, 1999</p>
<p>Revised&nbsp; <!--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 &quot;as is&quot;

View File

@@ -16,19 +16,29 @@ expression.)&nbsp;&nbsp; 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>.&nbsp;
See <a href="#scoped_ptr_example">example</a>.</p>
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
needs.&nbsp; It cannot be used in C++ Standard Library containers.&nbsp; See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
needs.&nbsp; It supplies a basic &quot;resource acquisition is
initialization&quot; facility, without shared-ownership or transfer-of-ownership
semantics.&nbsp; 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.&nbsp;
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.&nbsp; (Because of the &quot;complete type&quot;
requirement for delete and reset members, they may have one additional function
call overhead in certain idioms.&nbsp; See <a href="#Handle/Body">Handle/Body
Idiom</a>.)&nbsp;&nbsp;&nbsp;</p>
<p>Class<strong> scoped_ptr</strong> cannot be used in C++ Standard Library containers.&nbsp; 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.&nbsp; 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.&nbsp;&nbsp; <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 &lt;boost/smart_ptr.hpp&gt;
<pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost {
template&lt;typename T&gt; class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
@@ -52,8 +62,10 @@ template&lt;typename T&gt; 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.&nbsp;
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.&nbsp; 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-&gt;">operator-&gt;</a> and <a name="scoped_ptr_get">get</a></h3>
<pre>T* operator-&gt;() const; // never throws
T* get() const; // never throws</pre>
<p><b>T</b> is not required by get() be a complete type.&nbsp; 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 &lt;iostream&gt;
@@ -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&lt;body&gt; imp;
};</pre>
<p>This code requires that <code>class body</code> have a trivial destructor to
avoid undefined behavior.&nbsp; This is because the definition of <code>class
body</code> is not visible at the time scoped_ptr&lt;&gt; deletes it. See ISO
5.3.5/5.&nbsp; 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.)&nbsp;</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&lt;T&gt;</b> is equivalent to
<b>std::auto_ptr&lt;T> const</b>.&nbsp; Ed Brey pointed out, however, that
reset() will not work on a <b>std::auto_ptr&lt;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&lt;&gt;</b> to an incomplete type to hide the
implementation.&nbsp;&nbsp; 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.&nbsp; 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 &quot;as is&quot;

16
scoped_ptr_example.cpp Normal file
View 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
View 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
};

View 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;
}

View File

@@ -23,20 +23,20 @@ shared_array</strong> works by default for Standard Library's Associative
Container Compare template parameter.&nbsp; For compilers not supporting partial
specialization, the user must explicitly pass the less&lt;&gt; functor.</p>
<p>Class<strong> shared_array</strong> cannot correctly hold a pointer to a
single object.&nbsp; See <a href="shared_ptr.htm"><strong>shared_array</strong></a>
single object.&nbsp; 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.&nbsp;&nbsp; <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 &lt;boost/smart_ptr.hpp&gt;
<pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost {
template&lt;typename T&gt; 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.&nbsp;
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.&nbsp;
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.&nbsp;
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&lt;T&gt;&amp; other ) throw()</code></p>
<p><b>T</b> is not required be a complete type.&nbsp;
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 &quot;as is&quot;

View File

@@ -34,7 +34,7 @@ object A dangling with a use_count() of 1.</p>
pointed to.&nbsp;&nbsp; <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 &lt;boost/smart_ptr.hpp&gt;
<pre>#include &lt;<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>&gt;
namespace boost {
template&lt;typename T&gt; class shared_ptr {
@@ -180,21 +180,58 @@ an exception is thrown,&nbsp; <tt>delete p</tt> is called.</p>
<h3>shared_ptr <a name="shared_ptr_operator-&gt;">operator-&gt;</a> and <a name="shared_ptr_get">get</a></h3>
<pre>T* operator-&gt;() const; // never throws
T* get() const; // never throws</pre>
<p><b>T</b> is not required by get() to be a complete type .&nbsp; 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.&nbsp;
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.&nbsp;
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&lt;T&gt;&amp; other ) throw()</code></p>
<p><b>T</b> is not required be a complete type.&nbsp;
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.&nbsp; Furthermore, use_count() may be even higher
at various times while push_back() and insert() container operations are performed.&nbsp;
More complicated yet, the container operations may throw exceptions under a
variety of circumstances.&nbsp; 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&lt;&gt;</b> to an incomplete type to hide the
implementation.&nbsp;&nbsp; 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>FAQ</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.&nbsp; <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.&nbsp; Until then, <b>shared_ptr</b> is the
smart pointer of choice for a wide range of applications.</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>
<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 &quot;as is&quot;

96
shared_ptr_example.cpp Normal file
View 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
View 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
View 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
};

View 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;
}

View File

@@ -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.&nbsp; 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.&nbsp; 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.&nbsp; In these idioms a
smart pointer may appear in translation units where <tt><b>T</b></tt> is an
incomplete type.&nbsp; This separates interface from implementation and hides
implementation from translation units which merely use the interface.&nbsp;
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
&quot;no effect&quot; or &quot;no effect except such-and-such&quot; 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.&nbsp; 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&nbsp; <!--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

View File

@@ -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;

View File

@@ -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 -->27 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14992" -->
</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