mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-10-05 20:21:04 +02:00
Compare commits
1 Commits
boost-1.20
...
boost-1.22
Author | SHA1 | Date | |
---|---|---|---|
|
a59fb9bccd |
@@ -9,6 +9,10 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 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)
|
// 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams)
|
||||||
// 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
|
// 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
|
||||||
// 24 Jul 00 Change throw() to // never throws. See lib guidelines
|
// 24 Jul 00 Change throw() to // never throws. See lib guidelines
|
||||||
@@ -52,8 +56,14 @@
|
|||||||
#include <cstddef> // for std::size_t
|
#include <cstddef> // for std::size_t
|
||||||
#include <memory> // for std::auto_ptr
|
#include <memory> // for std::auto_ptr
|
||||||
#include <algorithm> // for std::swap
|
#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 <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 {
|
namespace boost {
|
||||||
|
|
||||||
@@ -72,18 +82,10 @@ template<typename T> class scoped_ptr : noncopyable {
|
|||||||
typedef T element_type;
|
typedef T element_type;
|
||||||
|
|
||||||
explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws
|
explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws
|
||||||
~scoped_ptr() { delete ptr; }
|
~scoped_ptr() { checked_delete(ptr); }
|
||||||
|
void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } }
|
||||||
void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } }
|
|
||||||
T& operator*() const { return *ptr; } // never throws
|
T& operator*() const { return *ptr; } // never throws
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# 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
|
|
||||||
T* operator->() const { return ptr; } // never throws
|
T* operator->() const { return ptr; } // never throws
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
T* get() const { return ptr; } // never throws
|
T* get() const { return ptr; } // never throws
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||||
@@ -105,9 +107,10 @@ template<typename T> class scoped_array : noncopyable {
|
|||||||
typedef T element_type;
|
typedef T element_type;
|
||||||
|
|
||||||
explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws
|
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
|
T* get() const { return ptr; } // never throws
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||||
@@ -130,7 +133,7 @@ template<typename T> class shared_ptr {
|
|||||||
|
|
||||||
explicit shared_ptr(T* p =0) : px(p) {
|
explicit shared_ptr(T* p =0) : px(p) {
|
||||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
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(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
|
||||||
@@ -165,7 +168,7 @@ template<typename T> class shared_ptr {
|
|||||||
template<typename Y>
|
template<typename Y>
|
||||||
shared_ptr& operator=(std::auto_ptr<Y>& r) {
|
shared_ptr& operator=(std::auto_ptr<Y>& r) {
|
||||||
// code choice driven by guarantee of "no effect if new throws"
|
// 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
|
else { // allocate new reference counter
|
||||||
long * tmp = new long(1); // may throw
|
long * tmp = new long(1); // may throw
|
||||||
--*pn; // only decrement once danger of new throwing is past
|
--*pn; // only decrement once danger of new throwing is past
|
||||||
@@ -184,7 +187,7 @@ template<typename T> class shared_ptr {
|
|||||||
|
|
||||||
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
||||||
// code choice driven by guarantee of "no effect if new throws"
|
// 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
|
else { // allocate new reference counter
|
||||||
long * tmp = new long(1); // may throw
|
long * tmp = new long(1); // may throw
|
||||||
--*pn; // only decrement once danger of new throwing is past
|
--*pn; // only decrement once danger of new throwing is past
|
||||||
@@ -198,12 +201,12 @@ template<typename T> class shared_ptr {
|
|||||||
|
|
||||||
void reset(T* p=0) {
|
void reset(T* p=0) {
|
||||||
if ( px == p ) return; // fix: self-assignment safe
|
if ( px == p ) return; // fix: self-assignment safe
|
||||||
if (--*pn == 0) { delete px; }
|
if (--*pn == 0) { checked_delete(px); }
|
||||||
else { // allocate new reference counter
|
else { // allocate new reference counter
|
||||||
try { pn = new long; } // fix: prevent leak if new throws
|
try { pn = new long; } // fix: prevent leak if new throws
|
||||||
catch (...) {
|
catch (...) {
|
||||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
++*pn; // undo effect of --*pn above to meet effects guarantee
|
||||||
delete p;
|
checked_delete(p);
|
||||||
throw;
|
throw;
|
||||||
} // catch
|
} // catch
|
||||||
} // allocate new reference counter
|
} // allocate new reference counter
|
||||||
@@ -212,14 +215,7 @@ template<typename T> class shared_ptr {
|
|||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
T& operator*() const { return *px; } // never throws
|
T& operator*() const { return *px; } // never throws
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# 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
|
|
||||||
T* operator->() const { return px; } // never throws
|
T* operator->() const { return px; } // never throws
|
||||||
#ifdef BOOST_MSVC
|
|
||||||
# pragma warning(pop)
|
|
||||||
#endif
|
|
||||||
T* get() const { return px; } // never throws
|
T* get() const { return px; } // never throws
|
||||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||||
@@ -247,13 +243,15 @@ template<typename T> class shared_ptr {
|
|||||||
template<typename Y> friend class shared_ptr;
|
template<typename Y> friend class shared_ptr;
|
||||||
#endif
|
#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) {
|
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();
|
dispose();
|
||||||
px = rpx;
|
px = rpx;
|
||||||
++*(pn = rpn);
|
pn = rpn;
|
||||||
}
|
}
|
||||||
} // share
|
} // share
|
||||||
}; // shared_ptr
|
}; // shared_ptr
|
||||||
@@ -278,7 +276,7 @@ template<typename T> class shared_array {
|
|||||||
|
|
||||||
explicit shared_array(T* p =0) : px(p) {
|
explicit shared_array(T* p =0) : px(p) {
|
||||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
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
|
shared_array(const shared_array& r) : px(r.px) // never throws
|
||||||
@@ -287,22 +285,24 @@ template<typename T> class shared_array {
|
|||||||
~shared_array() { dispose(); }
|
~shared_array() { dispose(); }
|
||||||
|
|
||||||
shared_array& operator=(const shared_array& r) {
|
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();
|
dispose();
|
||||||
px = r.px;
|
px = r.px;
|
||||||
++*(pn = r.pn);
|
pn = r.pn;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
} // operator=
|
} // operator=
|
||||||
|
|
||||||
void reset(T* p=0) {
|
void reset(T* p=0) {
|
||||||
if ( px == p ) return; // fix: self-assignment safe
|
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
|
else { // allocate new reference counter
|
||||||
try { pn = new long; } // fix: prevent leak if new throws
|
try { pn = new long; } // fix: prevent leak if new throws
|
||||||
catch (...) {
|
catch (...) {
|
||||||
++*pn; // undo effect of --*pn above to meet effects guarantee
|
++*pn; // undo effect of --*pn above to meet effects guarantee
|
||||||
delete [] p;
|
checked_array_delete(p);
|
||||||
throw;
|
throw;
|
||||||
} // catch
|
} // catch
|
||||||
} // allocate new reference counter
|
} // allocate new reference counter
|
||||||
@@ -329,7 +329,7 @@ template<typename T> class shared_array {
|
|||||||
T* px; // contained pointer
|
T* px; // contained pointer
|
||||||
long* pn; // ptr to reference counter
|
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
|
}; // shared_array
|
||||||
|
|
||||||
@@ -389,6 +389,10 @@ template<typename T>
|
|||||||
|
|
||||||
#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
#ifdef BOOST_MSVC
|
||||||
|
# pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // BOOST_SMART_PTR_HPP
|
#endif // BOOST_SMART_PTR_HPP
|
||||||
|
|
||||||
|
|
||||||
|
@@ -27,11 +27,10 @@ expressions.
|
|||||||
<li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
|
<li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
|
||||||
<li>Header <a href="../../boost/smart_ptr.hpp">smart_ptr.hpp</a></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>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
|
<li>Submitted by <a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/beman_dawes.html">Beman
|
||||||
Dawes</a>.</li>
|
Dawes</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Nov 2000<!--webbot bot="Timestamp" endspan i-checksum="15233" -->
|
<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>
|
</p>
|
||||||
|
|
||||||
</body>
|
</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,
|
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>
|
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
|
<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>
|
if <strong>scoped_array</strong> does not meet your needs.</p>
|
||||||
<p>Class<strong> scoped_array</strong> cannot correctly hold a pointer to a
|
<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>
|
single object. See <a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a>
|
||||||
for that usage.</p>
|
for that usage.</p>
|
||||||
<p>Because <strong>scoped_array</strong> is so simple, in its usual
|
<p>A C++ Standard Library <strong>vector</strong> is a <strong> </strong>heavier duty alternative to a <strong>scoped_array</strong>.</p>
|
||||||
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>The class is a template parameterized on <tt>T</tt>, the type of the object
|
<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
|
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
||||||
requirements</a>.</p>
|
requirements</a>.</p>
|
||||||
<h2>Class scoped_array Synopsis</h2>
|
<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 {
|
namespace boost {
|
||||||
|
|
||||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
|
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>
|
<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
|
<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>
|
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>
|
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
|
||||||
<pre>~scoped_array();</pre>
|
<pre>~scoped_array();</pre>
|
||||||
<p>Deletes the array pointed to by the stored pointer. Note that in C++ <tt>delete</tt>[]
|
<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>
|
in the array.</p>
|
||||||
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
|
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
|
||||||
<pre>T* get() const; // never throws</pre>
|
<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>
|
<p>Returns the stored pointer.</p>
|
||||||
<h2>Class <a name="shared_array_example">scoped_array example</a></h2>
|
<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>
|
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||||
<hr>
|
<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,
|
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
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>.
|
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>
|
See <a href="#scoped_ptr_example">example</a>.</p>
|
||||||
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
|
<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>
|
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
|
<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>
|
dynamically allocated array. See <a href="scoped_array.htm"><strong>scoped_array</strong></a>
|
||||||
for that usage.</p>
|
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
|
<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
|
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
||||||
requirements</a>.</p>
|
requirements</a>.</p>
|
||||||
<h2>Class scoped_ptr Synopsis</h2>
|
<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 {
|
namespace boost {
|
||||||
|
|
||||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
|
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>
|
<p>Provides the type of the stored pointer.</p>
|
||||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
|
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
|
||||||
<pre>explicit scoped_ptr( T* p=0 ); // never throws</pre>
|
<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
|
<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>
|
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
|
||||||
<pre>~scoped_ptr();</pre>
|
<pre>~scoped_ptr();</pre>
|
||||||
<p>Deletes the object pointed to by the stored pointer. Note that in C++, <tt>delete</tt>
|
<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>
|
<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
|
<pre>T* operator->() const; // never throws
|
||||||
T* get() const; // never throws</pre>
|
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>
|
<p>Both return the stored pointer.</p>
|
||||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
|
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
|
||||||
<pre>#include <iostream>
|
<pre>#include <iostream>
|
||||||
@@ -98,25 +111,37 @@ output:</p>
|
|||||||
2
|
2
|
||||||
Buckle my shoe</pre>
|
Buckle my shoe</pre>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
<h2>Handle/Body Idiom</h2>
|
<h2>Rationale</h2>
|
||||||
<p>One common usage of <b>shared_pointer</b> is to implement a handle/body
|
<p>The primary reason to use <b> scoped_ptr</b> rather than <b> auto_ptr</b> is to let readers
|
||||||
structure which avoids exposing the body (implementation) in the header file:</p>
|
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
|
||||||
<pre>class handle
|
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
|
||||||
public: // simple forwarding functions to the body class
|
ownership by returning the <b> auto_ptr</b> (because the maintenance programmer saw
|
||||||
void f();
|
<b>auto_ptr</b>, and assumed ownership could safely be transferred.) </p>
|
||||||
void g(int);
|
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b> bool</b> is usually
|
||||||
private:
|
just an <b>int</b>. Indeed, some argued against including <b> bool</b> in the
|
||||||
friend class body; //incomplete class hides implementation
|
C++ standard because of that. But by coding <b> bool</b> rather than <b> int</b>, you tell your readers
|
||||||
boost::scoped_ptr<body> imp;
|
what your intent is. Same with <b> scoped_ptr</b> - you are signaling intent.</p>
|
||||||
};</pre>
|
<p>It has been suggested that <b>boost::scoped_ptr<T></b> is equivalent to
|
||||||
<p>This code requires that <code>class body</code> have a trivial destructor to
|
<b>std::auto_ptr<T> const</b>. Ed Brey pointed out, however, that
|
||||||
avoid undefined behavior. This is because the definition of <code>class
|
reset() will not work on a <b>std::auto_ptr<T> const.</b></p>
|
||||||
body</code> is not visible at the time scoped_ptr<> deletes it. See ISO
|
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
|
||||||
5.3.5/5. Note that some compilers will issue a warning even though the
|
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also
|
||||||
above code is well defined.</p>
|
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>
|
<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,
|
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
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;
|
||||||
|
}
|
@@ -30,13 +30,13 @@ 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
|
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
|
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>
|
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>
|
<p>A C++ Standard Library <strong>vector</strong> is <strong> </strong>a <strong>
|
||||||
to a C++ Standard Library <strong>vector</strong>.</p>
|
</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
|
<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
|
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
||||||
requirements</a>.</p>
|
requirements</a>.</p>
|
||||||
<h2>Class shared_array Synopsis</h2>
|
<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 {
|
namespace boost {
|
||||||
|
|
||||||
template<typename T> class shared_array {
|
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>
|
in the array.</p>
|
||||||
<h3>shared_array <a name="shared_array_get">get</a></h3>
|
<h3>shared_array <a name="shared_array_get">get</a></h3>
|
||||||
<pre>T* get() const; // never throws</pre>
|
<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>
|
<p>Returns the stored pointer.</p>
|
||||||
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
|
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
|
||||||
<p><tt>long use_count() const; // never throws</tt></p>
|
<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
|
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
|
||||||
stored pointer.</p>
|
stored pointer.</p>
|
||||||
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
|
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
|
||||||
<p><tt>bool unique() const; // never throws</tt></p>
|
<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>
|
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
|
<h3><a name="shared_array_swap">shared_array swap</a></h3>
|
||||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
|
<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>
|
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
||||||
<h2>Class <a name="shared_array_example">shared_array example</a></h2>
|
<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>
|
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||||
<hr>
|
<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,
|
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
notice appears in all copies. This document is provided "as is"
|
||||||
|
@@ -34,7 +34,7 @@ object A dangling with a use_count() of 1.</p>
|
|||||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
||||||
requirements</a>.</p>
|
requirements</a>.</p>
|
||||||
<h2>Class shared_ptr Synopsis</h2>
|
<h2>Class shared_ptr Synopsis</h2>
|
||||||
<pre>#include <boost/smart_ptr.hpp>
|
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
|
||||||
template<typename T> class shared_ptr {
|
template<typename T> class shared_ptr {
|
||||||
@@ -180,45 +180,57 @@ 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>
|
<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
|
<pre>T* operator->() const; // never throws
|
||||||
T* get() const; // never throws</pre>
|
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>
|
<p>Both return the stored pointer.</p>
|
||||||
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
|
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
|
||||||
<p><tt>long use_count() const; // never throws</tt></p>
|
<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
|
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
|
||||||
stored pointer.</p>
|
stored pointer.</p>
|
||||||
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
|
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
|
||||||
<p><tt>bool unique() const; // never throws</tt></p>
|
<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>
|
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
|
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
|
||||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
|
<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>
|
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
||||||
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
|
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
|
||||||
<pre>// The application will produce a series of
|
<p>See <a href="shared_ptr_example.cpp"> shared_ptr_example.cpp</a> for a complete example program.</p>
|
||||||
// objects of type Foo which later must be
|
<p>This program builds a std::vector and std::set of FooPtr's.</p>
|
||||||
// accessed both by occurrence (std::vector)
|
<p>Note that after the two containers have been populated, some of the FooPtr objects
|
||||||
// and by ordering relationship (std::set).
|
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
|
||||||
class Foo { ... };
|
at various times while push_back() and insert() container operations are performed.
|
||||||
|
|
||||||
typedef boost::shared_ptr<Foo> FooPtr;
|
|
||||||
|
|
||||||
std::vector<FooPtr> foo_vector;
|
|
||||||
std::set<FooPtr> foo_set; // NOT multiset!
|
|
||||||
|
|
||||||
...
|
|
||||||
{ // creation loop
|
|
||||||
FooPtr foo_ptr ( new Foo( ... ) );
|
|
||||||
foo_vector.push_back( foo_ptr );
|
|
||||||
foo_set.insert( foo_ptr );
|
|
||||||
}</pre>
|
|
||||||
<p>Note that at the termination of the creation loop, some of the FooPtr objects
|
|
||||||
may have use_count()==1 rather than use_count()==2, since foo_set is a std::set
|
|
||||||
rather than a std::multiset. Furthermore, use_count() will be even higher
|
|
||||||
at various times inside the loop, as container operations are performed.
|
|
||||||
More complicated yet, the container operations may throw exceptions under a
|
More complicated yet, the container operations may throw exceptions under a
|
||||||
variety of circumstances. Without using a smart pointer, memory and
|
variety of circumstances. Without using a smart pointer, memory and
|
||||||
exception management would be a nightmare.</p>
|
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>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. <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.</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>
|
<hr>
|
||||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40412" -->
|
<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>
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
|
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>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<p align="left"><a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a></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>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="scoped_array.htm"><strong>scoped_array</strong></a></td>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="shared_ptr.htm"><strong>shared_ptr</strong></a></td>
|
<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
|
<p>A page on <a href="smarttests.htm">Smart Pointer Timings</a> will be of
|
||||||
interest to those curious about performance issues.</p>
|
interest to those curious about performance issues.</p>
|
||||||
<h2><a name="Common requirements">Common requirements</a></h2>
|
<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
|
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
|
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>
|
<h2>Exception safety</h2>
|
||||||
<p>Several functions in these smart pointer classes are specified as having
|
<p>Several functions in these smart pointer classes are specified as having
|
||||||
"no effect" or "no effect except such-and-such" if an
|
"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
|
<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>
|
throwing exceptions by the <a href="#Common requirements">Common requirements</a>.</p>
|
||||||
<h2>History and acknowledgements</h2>
|
<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
|
<p>November, 1999. Darin Adler provided operator ==, operator !=, and std::swap
|
||||||
and std::less specializations for shared types.</p>
|
and std::less specializations for shared types.</p>
|
||||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</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>
|
<p>See the Revision History section of the header for further contributors.</p>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
|
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
|
||||||
-->24 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14986"
|
-->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110"
|
||||||
--></p>
|
--></p>
|
||||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
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.
|
// implied warranty, and with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
// Revision History
|
// 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)
|
// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
|
||||||
// 25 Sep 99 added swap tests
|
// 25 Sep 99 added swap tests
|
||||||
// 20 Jul 99 header name changed to .hpp
|
// 20 Jul 99 header name changed to .hpp
|
||||||
// 20 Apr 99 additional error tests added.
|
// 20 Apr 99 additional error tests added.
|
||||||
|
|
||||||
|
#define BOOST_INCLUDE_MAIN
|
||||||
|
#include <boost/test/test_tools.hpp>
|
||||||
#include <boost/smart_ptr.hpp>
|
#include <boost/smart_ptr.hpp>
|
||||||
#include <cassert>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#ifdef NDEBUG
|
class Incomplete;
|
||||||
#error This test program makes no sense if NDEBUG is defined
|
|
||||||
#endif
|
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
|
||||||
|
{
|
||||||
|
return incomplete.get();
|
||||||
|
}
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using boost::scoped_ptr;
|
using boost::scoped_ptr;
|
||||||
@@ -28,7 +34,7 @@ using boost::shared_ptr;
|
|||||||
using boost::shared_array;
|
using boost::shared_array;
|
||||||
|
|
||||||
template<typename T>
|
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 {
|
namespace {
|
||||||
int UDT_use_count; // independent of pointer maintained counts
|
int UDT_use_count; // independent of pointer maintained counts
|
||||||
@@ -48,169 +54,189 @@ class UDT {
|
|||||||
void value( long v ) { value_ = v;; }
|
void value( long v ) { value_ = v;; }
|
||||||
}; // UDT
|
}; // 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 --------------------------------------------------------------------//
|
// main --------------------------------------------------------------------//
|
||||||
|
|
||||||
// This isn't a very systematic test; it just hits some of the basics.
|
// 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
|
// test scoped_ptr with a built-in type
|
||||||
long * lp = new long;
|
long * lp = new long;
|
||||||
scoped_ptr<long> sp ( lp );
|
scoped_ptr<long> sp ( lp );
|
||||||
assert( sp.get() == lp );
|
BOOST_TEST( sp.get() == lp );
|
||||||
assert( lp == sp.get() );
|
BOOST_TEST( lp == sp.get() );
|
||||||
assert( &*sp == lp );
|
BOOST_TEST( &*sp == lp );
|
||||||
|
|
||||||
*sp = 1234568901L;
|
*sp = 1234568901L;
|
||||||
assert( *sp == 1234568901L );
|
BOOST_TEST( *sp == 1234568901L );
|
||||||
assert( *lp == 1234568901L );
|
BOOST_TEST( *lp == 1234568901L );
|
||||||
ck( static_cast<long*>(sp.get()), 1234568901L );
|
ck( static_cast<long*>(sp.get()), 1234568901L );
|
||||||
ck( lp, *sp );
|
ck( lp, *sp );
|
||||||
|
|
||||||
sp.reset();
|
sp.reset();
|
||||||
assert( sp.get() == 0 );
|
BOOST_TEST( sp.get() == 0 );
|
||||||
|
|
||||||
// test scoped_ptr with a user defined type
|
// test scoped_ptr with a user defined type
|
||||||
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
|
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();
|
||||||
udt_sp.reset( new UDT( 111222333 ) );
|
udt_sp.reset( new UDT( 111222333 ) );
|
||||||
assert( udt_sp->value() == 111222333 );
|
BOOST_TEST( udt_sp->value() == 111222333 );
|
||||||
udt_sp.reset( new UDT( 333222111 ) );
|
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
|
// test scoped_array with a build-in type
|
||||||
char * sap = new char [ 100 ];
|
char * sap = new char [ 100 ];
|
||||||
scoped_array<char> sa ( sap );
|
scoped_array<char> sa ( sap );
|
||||||
assert( sa.get() == sap );
|
BOOST_TEST( sa.get() == sap );
|
||||||
assert( sap == sa.get() );
|
BOOST_TEST( sap == sa.get() );
|
||||||
|
|
||||||
strcpy( sa.get(), "Hot Dog with mustard and relish" );
|
strcpy( sa.get(), "Hot Dog with mustard and relish" );
|
||||||
assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||||
assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
||||||
|
|
||||||
assert( sa[0] == 'H' );
|
BOOST_TEST( sa[0] == 'H' );
|
||||||
assert( sa[30] == 'h' );
|
BOOST_TEST( sa[30] == 'h' );
|
||||||
|
|
||||||
sa[0] = 'N';
|
sa[0] = 'N';
|
||||||
sa[4] = 'd';
|
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();
|
sa.reset();
|
||||||
assert( sa.get() == 0 );
|
BOOST_TEST( sa.get() == 0 );
|
||||||
|
|
||||||
// test shared_ptr with a built-in type
|
// test shared_ptr with a built-in type
|
||||||
int * ip = new int;
|
int * ip = new int;
|
||||||
shared_ptr<int> cp ( ip );
|
shared_ptr<int> cp ( ip );
|
||||||
assert( ip == cp.get() );
|
BOOST_TEST( ip == cp.get() );
|
||||||
assert( cp.use_count() == 1 );
|
BOOST_TEST( cp.use_count() == 1 );
|
||||||
|
|
||||||
*cp = 54321;
|
*cp = 54321;
|
||||||
assert( *cp == 54321 );
|
BOOST_TEST( *cp == 54321 );
|
||||||
assert( *ip == 54321 );
|
BOOST_TEST( *ip == 54321 );
|
||||||
ck( static_cast<int*>(cp.get()), 54321 );
|
ck( static_cast<int*>(cp.get()), 54321 );
|
||||||
ck( static_cast<int*>(ip), *cp );
|
ck( static_cast<int*>(ip), *cp );
|
||||||
|
|
||||||
shared_ptr<int> cp2 ( cp );
|
shared_ptr<int> cp2 ( cp );
|
||||||
assert( ip == cp2.get() );
|
BOOST_TEST( ip == cp2.get() );
|
||||||
assert( cp.use_count() == 2 );
|
BOOST_TEST( cp.use_count() == 2 );
|
||||||
assert( cp2.use_count() == 2 );
|
BOOST_TEST( cp2.use_count() == 2 );
|
||||||
|
|
||||||
assert( *cp == 54321 );
|
BOOST_TEST( *cp == 54321 );
|
||||||
assert( *cp2 == 54321 );
|
BOOST_TEST( *cp2 == 54321 );
|
||||||
ck( static_cast<int*>(cp2.get()), 54321 );
|
ck( static_cast<int*>(cp2.get()), 54321 );
|
||||||
ck( static_cast<int*>(ip), *cp2 );
|
ck( static_cast<int*>(ip), *cp2 );
|
||||||
|
|
||||||
shared_ptr<int> cp3 ( cp );
|
shared_ptr<int> cp3 ( cp );
|
||||||
assert( cp.use_count() == 3 );
|
BOOST_TEST( cp.use_count() == 3 );
|
||||||
assert( cp2.use_count() == 3 );
|
BOOST_TEST( cp2.use_count() == 3 );
|
||||||
assert( cp3.use_count() == 3 );
|
BOOST_TEST( cp3.use_count() == 3 );
|
||||||
cp.reset();
|
cp.reset();
|
||||||
assert( cp2.use_count() == 2 );
|
BOOST_TEST( cp2.use_count() == 2 );
|
||||||
assert( cp3.use_count() == 2 );
|
BOOST_TEST( cp3.use_count() == 2 );
|
||||||
assert( cp.use_count() == 1 );
|
BOOST_TEST( cp.use_count() == 1 );
|
||||||
cp.reset( new int );
|
cp.reset( new int );
|
||||||
*cp = 98765;
|
*cp = 98765;
|
||||||
assert( *cp == 98765 );
|
BOOST_TEST( *cp == 98765 );
|
||||||
*cp3 = 87654;
|
*cp3 = 87654;
|
||||||
assert( *cp3 == 87654 );
|
BOOST_TEST( *cp3 == 87654 );
|
||||||
assert( *cp2 == 87654 );
|
BOOST_TEST( *cp2 == 87654 );
|
||||||
cp.swap( cp3 );
|
cp.swap( cp3 );
|
||||||
assert( *cp == 87654 );
|
BOOST_TEST( *cp == 87654 );
|
||||||
assert( *cp2 == 87654 );
|
BOOST_TEST( *cp2 == 87654 );
|
||||||
assert( *cp3 == 98765 );
|
BOOST_TEST( *cp3 == 98765 );
|
||||||
cp.swap( cp3 );
|
cp.swap( cp3 );
|
||||||
assert( *cp == 98765 );
|
BOOST_TEST( *cp == 98765 );
|
||||||
assert( *cp2 == 87654 );
|
BOOST_TEST( *cp2 == 87654 );
|
||||||
assert( *cp3 == 87654 );
|
BOOST_TEST( *cp3 == 87654 );
|
||||||
cp2 = cp2;
|
cp2 = cp2;
|
||||||
assert( cp2.use_count() == 2 );
|
BOOST_TEST( cp2.use_count() == 2 );
|
||||||
assert( *cp2 == 87654 );
|
BOOST_TEST( *cp2 == 87654 );
|
||||||
cp = cp2;
|
cp = cp2;
|
||||||
assert( cp2.use_count() == 3 );
|
BOOST_TEST( cp2.use_count() == 3 );
|
||||||
assert( *cp2 == 87654 );
|
BOOST_TEST( *cp2 == 87654 );
|
||||||
assert( cp.use_count() == 3 );
|
BOOST_TEST( cp.use_count() == 3 );
|
||||||
assert( *cp == 87654 );
|
BOOST_TEST( *cp == 87654 );
|
||||||
|
|
||||||
shared_ptr<int> cp4;
|
shared_ptr<int> cp4;
|
||||||
swap( cp2, cp4 );
|
swap( cp2, cp4 );
|
||||||
assert( cp4.use_count() == 3 );
|
BOOST_TEST( cp4.use_count() == 3 );
|
||||||
assert( *cp4 == 87654 );
|
BOOST_TEST( *cp4 == 87654 );
|
||||||
assert( cp2.get() == 0 );
|
BOOST_TEST( cp2.get() == 0 );
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
set< shared_ptr<int> > scp;
|
set< shared_ptr<int> > scp;
|
||||||
scp.insert(cp4);
|
scp.insert(cp4);
|
||||||
assert( scp.find(cp4) != scp.end() );
|
BOOST_TEST( scp.find(cp4) != scp.end() );
|
||||||
assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// test shared_array with a built-in type
|
// test shared_array with a built-in type
|
||||||
char * cap = new char [ 100 ];
|
char * cap = new char [ 100 ];
|
||||||
shared_array<char> ca ( cap );
|
shared_array<char> ca ( cap );
|
||||||
assert( ca.get() == cap );
|
BOOST_TEST( ca.get() == cap );
|
||||||
assert( cap == ca.get() );
|
BOOST_TEST( cap == ca.get() );
|
||||||
assert( &ca[0] == cap );
|
BOOST_TEST( &ca[0] == cap );
|
||||||
|
|
||||||
strcpy( ca.get(), "Hot Dog with mustard and relish" );
|
strcpy( ca.get(), "Hot Dog with mustard and relish" );
|
||||||
assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||||
assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
||||||
|
|
||||||
assert( ca[0] == 'H' );
|
BOOST_TEST( ca[0] == 'H' );
|
||||||
assert( ca[30] == 'h' );
|
BOOST_TEST( ca[30] == 'h' );
|
||||||
|
|
||||||
shared_array<char> ca2 ( ca );
|
shared_array<char> ca2 ( ca );
|
||||||
shared_array<char> ca3 ( ca2 );
|
shared_array<char> ca3 ( ca2 );
|
||||||
|
|
||||||
ca[0] = 'N';
|
ca[0] = 'N';
|
||||||
ca[4] = 'd';
|
ca[4] = 'd';
|
||||||
assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
||||||
assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
||||||
assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
||||||
assert( ca.use_count() == 3 );
|
BOOST_TEST( ca.use_count() == 3 );
|
||||||
assert( ca2.use_count() == 3 );
|
BOOST_TEST( ca2.use_count() == 3 );
|
||||||
assert( ca3.use_count() == 3 );
|
BOOST_TEST( ca3.use_count() == 3 );
|
||||||
ca2.reset();
|
ca2.reset();
|
||||||
assert( ca.use_count() == 2 );
|
BOOST_TEST( ca.use_count() == 2 );
|
||||||
assert( ca3.use_count() == 2 );
|
BOOST_TEST( ca3.use_count() == 2 );
|
||||||
assert( ca2.use_count() == 1 );
|
BOOST_TEST( ca2.use_count() == 1 );
|
||||||
|
|
||||||
ca.reset();
|
ca.reset();
|
||||||
assert( ca.get() == 0 );
|
BOOST_TEST( ca.get() == 0 );
|
||||||
|
|
||||||
shared_array<char> ca4;
|
shared_array<char> ca4;
|
||||||
swap( ca3, ca4 );
|
swap( ca3, ca4 );
|
||||||
assert( ca4.use_count() == 1 );
|
BOOST_TEST( ca4.use_count() == 1 );
|
||||||
assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
||||||
assert( ca3.get() == 0 );
|
BOOST_TEST( ca3.get() == 0 );
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
set< shared_array<char> > sca;
|
set< shared_array<char> > sca;
|
||||||
sca.insert(ca4);
|
sca.insert(ca4);
|
||||||
assert( sca.find(ca4) != sca.end() );
|
BOOST_TEST( sca.find(ca4) != sca.end() );
|
||||||
assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// test shared_array with user defined type
|
// test shared_array with user defined type
|
||||||
@@ -221,38 +247,38 @@ int main() {
|
|||||||
udta[2].value( 333 );
|
udta[2].value( 333 );
|
||||||
shared_array<UDT> udta2 ( udta );
|
shared_array<UDT> udta2 ( udta );
|
||||||
|
|
||||||
assert( udta[0].value() == 111 );
|
BOOST_TEST( udta[0].value() == 111 );
|
||||||
assert( udta[1].value() == 222 );
|
BOOST_TEST( udta[1].value() == 222 );
|
||||||
assert( udta[2].value() == 333 );
|
BOOST_TEST( udta[2].value() == 333 );
|
||||||
assert( udta2[0].value() == 111 );
|
BOOST_TEST( udta2[0].value() == 111 );
|
||||||
assert( udta2[1].value() == 222 );
|
BOOST_TEST( udta2[1].value() == 222 );
|
||||||
assert( udta2[2].value() == 333 );
|
BOOST_TEST( udta2[2].value() == 333 );
|
||||||
udta2.reset();
|
udta2.reset();
|
||||||
assert( udta2.get() == 0 );
|
BOOST_TEST( udta2.get() == 0 );
|
||||||
assert( udta.use_count() == 1 );
|
BOOST_TEST( udta.use_count() == 1 );
|
||||||
assert( udta2.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
|
// test shared_ptr with a user defined type
|
||||||
UDT * up = new UDT;
|
UDT * up = new UDT;
|
||||||
shared_ptr<UDT> sup ( up );
|
shared_ptr<UDT> sup ( up );
|
||||||
assert( up == sup.get() );
|
BOOST_TEST( up == sup.get() );
|
||||||
assert( sup.use_count() == 1 );
|
BOOST_TEST( sup.use_count() == 1 );
|
||||||
|
|
||||||
sup->value( 54321 ) ;
|
sup->value( 54321 ) ;
|
||||||
assert( sup->value() == 54321 );
|
BOOST_TEST( sup->value() == 54321 );
|
||||||
assert( up->value() == 54321 );
|
BOOST_TEST( up->value() == 54321 );
|
||||||
|
|
||||||
shared_ptr<UDT> sup2;
|
shared_ptr<UDT> sup2;
|
||||||
sup2 = sup;
|
sup2 = sup;
|
||||||
assert( sup2->value() == 54321 );
|
BOOST_TEST( sup2->value() == 54321 );
|
||||||
assert( sup.use_count() == 2 );
|
BOOST_TEST( sup.use_count() == 2 );
|
||||||
assert( sup2.use_count() == 2 );
|
BOOST_TEST( sup2.use_count() == 2 );
|
||||||
sup2 = sup2;
|
sup2 = sup2;
|
||||||
assert( sup2->value() == 54321 );
|
BOOST_TEST( sup2->value() == 54321 );
|
||||||
assert( sup.use_count() == 2 );
|
BOOST_TEST( sup.use_count() == 2 );
|
||||||
assert( sup2.use_count() == 2 );
|
BOOST_TEST( sup2.use_count() == 2 );
|
||||||
|
|
||||||
cout << "OK" << endl;
|
cout << "OK" << endl;
|
||||||
|
|
||||||
|
@@ -530,7 +530,7 @@ Pointers Timings </h1>
|
|||||||
spreads its information as in the case of linked pointer.</li>
|
spreads its information as in the case of linked pointer.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
<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>
|
||||||
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
|
<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
|
and distribute this document is granted provided this copyright notice appears in all
|
||||||
|
Reference in New Issue
Block a user