forked from boostorg/smart_ptr
Smart pointer and utility changes related to adding checked_delere and checked_array_delete
[SVN r10189]
This commit is contained in:
@ -9,6 +9,7 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 Require complete type on delete (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)
|
||||
@ -54,8 +55,9 @@
|
||||
#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
|
||||
|
||||
namespace boost {
|
||||
|
||||
@ -74,9 +76,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
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(push)
|
||||
@ -107,9 +108,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
|
||||
@ -132,7 +134,7 @@ 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
|
||||
@ -167,7 +169,7 @@ template<typename T> class shared_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; }
|
||||
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
|
||||
@ -186,7 +188,7 @@ template<typename T> class shared_ptr {
|
||||
|
||||
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
|
||||
@ -200,12 +202,12 @@ template<typename T> class shared_ptr {
|
||||
|
||||
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
|
||||
@ -249,7 +251,7 @@ 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) { // Q: why not px != rpx? A: fails when both == 0
|
||||
@ -282,7 +284,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
|
||||
@ -303,12 +305,12 @@ template<typename T> class shared_array {
|
||||
|
||||
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
|
||||
@ -335,7 +337,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
|
||||
|
||||
|
@ -59,19 +59,27 @@ template<typename T> class scoped_array : <a href="../utility/utility.htm#
|
||||
<pre>explicit scoped_array( T* p=0 ); // never throws</pre>
|
||||
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
|
||||
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation.
|
||||
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><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Deletes the array pointed to by the stored pointer. Note that in C++ <tt>delete</tt>[]
|
||||
on a pointer with a value of 0 is harmless.</p>
|
||||
<p>Does not throw exceptions.</p>
|
||||
<h3>scoped_array <a name="scoped_array_reset">reset</a></h3>
|
||||
<pre>void reset( T* p=0 )();</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>If p is not equal to the stored pointer, deletes the array pointed to by the
|
||||
stored pointer and then stores a copy of p, which must have been allocated via a
|
||||
C++ <tt>new[]</tt> expression or be 0.</p>
|
||||
<p>Does not throw exceptions.</p>
|
||||
<h3>scoped_array <a name="scoped_array_operator[]">operator[]</a></h3>
|
||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
|
||||
stored pointer.</p>
|
||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
|
||||
@ -79,6 +87,8 @@ 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 at point of instantiation.
|
||||
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>
|
||||
|
@ -59,25 +59,38 @@ template<typename T> class scoped_ptr : <a href="../utility/utility.htm#cl
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
|
||||
<pre>explicit scoped_ptr( T* p=0 ); // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation.
|
||||
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><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Deletes the object pointed to by the stored pointer. Note that in C++, <tt>delete</tt>
|
||||
on a pointer with a value of 0 is harmless.</p>
|
||||
<p>Does not throw exceptions.</p>
|
||||
<h3>scoped_ptr <a name="scoped_ptr_reset">reset</a></h3>
|
||||
<pre>void reset( T* p=0 );</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>If p is not equal to the stored pointer, deletes the object pointed to by the
|
||||
stored pointer and then stores a copy of p, which must have been allocated via a
|
||||
C++ <tt>new</tt> expression or be 0.</p>
|
||||
<p>Does not throw exceptions.</p>
|
||||
<h3>scoped_ptr <a name="scoped_ptr_operator*">operator*</a></h3>
|
||||
<pre>T& operator*() const; // never throws</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
|
||||
<h3>scoped_ptr <a name="scoped_ptr_operator->">operator-></a> and <a name="scoped_ptr_get">get</a></h3>
|
||||
<pre>T* operator->() const; // never throws
|
||||
T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation of
|
||||
operator->(). See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation of
|
||||
get(). See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Both return the stored pointer.</p>
|
||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
|
||||
<pre>#include <iostream>
|
||||
@ -106,24 +119,16 @@ output:</p>
|
||||
Buckle my shoe</pre>
|
||||
</blockquote>
|
||||
<h2>Handle/Body Idiom</h2>
|
||||
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body
|
||||
structure which avoids exposing the body (implementation) in the header file:</p>
|
||||
<pre>class handle
|
||||
{
|
||||
public: // simple forwarding functions to the body class
|
||||
void f();
|
||||
void g(int);
|
||||
private:
|
||||
friend class body; //incomplete class hides implementation
|
||||
boost::scoped_ptr<body> imp;
|
||||
};</pre>
|
||||
<p>This code requires that <code>class body</code> have a trivial destructor to
|
||||
avoid undefined behavior. This is because the definition of <code>class
|
||||
body</code> is not visible at the time scoped_ptr<> deletes it. See ISO
|
||||
5.3.5/5. Note that some compilers will issue a warning even though the
|
||||
above code is well defined.</p>
|
||||
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body 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>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->21 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15104" --></p>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->22 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15106" --></p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
|
16
scoped_ptr_example.cpp
Normal file
16
scoped_ptr_example.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
// Boost scoped_ptr_example implementation file -----------------------------//
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
|
||||
void example::do_something() { std::cout << "did something\n"; }
|
||||
|
||||
example::~example() {}
|
21
scoped_ptr_example.hpp
Normal file
21
scoped_ptr_example.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
// Boost scoped_ptr_example header file ------------------------------------//
|
||||
|
||||
#include <boost/smart_ptr.hpp>
|
||||
|
||||
// The point of this example is to prove that even though
|
||||
// example::implementation is an incomplete type in translation units using
|
||||
// this header, scoped_ptr< implementation > is still valid because the type
|
||||
// is complete where it counts - in the inplementation translation unit where
|
||||
// destruction is actually instantiated.
|
||||
|
||||
class example : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
example();
|
||||
~example();
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::scoped_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
10
scoped_ptr_example_test.cpp
Normal file
10
scoped_ptr_example_test.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
// Boost scoped_ptr_example_test main program -------------------------------//
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example my_example;
|
||||
my_example.do_something();
|
||||
return 0;
|
||||
}
|
@ -108,17 +108,23 @@ name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="shared_array_ctor">shared_array constructors</a></h3>
|
||||
<pre>explicit shared_array( T* p=0 );</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Constructs a <strong>shared_array</strong>, storing a copy of <tt>p</tt>,
|
||||
which must have been allocated via a C++ <tt>new</tt>[] expression or be 0.
|
||||
Afterwards, use_count() is 1 (even if p==0; see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
|
||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>. If
|
||||
an exception is thrown, <tt>delete[] p</tt> is called.</p>
|
||||
<pre>shared_array( const shared_array& r); // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Constructs a <strong>shared_array</strong>, as if by storing a copy of the
|
||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
|
||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>.</p>
|
||||
<h3><a name="shared_array_~shared_array">shared_array destructor</a></h3>
|
||||
<pre>~shared_array();</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>If <strong>use_count()</strong> == 1, deletes the array pointed to by the
|
||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
|
||||
copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a pointer with
|
||||
@ -126,6 +132,8 @@ a value of 0 is harmless.</p>
|
||||
<p>Does not throw exceptions.</p>
|
||||
<h3>shared_array <a name="shared_array_operator=">operator=</a></h3>
|
||||
<pre>shared_array& operator=( const shared_array& r); // never throws</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
|
||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a
|
||||
@ -135,6 +143,8 @@ of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</st
|
||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>. </p>
|
||||
<h3>shared_array <a name="shared_array_reset">reset</a></h3>
|
||||
<pre>void reset( T* p=0 );</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
|
||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[]
|
||||
@ -147,6 +157,8 @@ see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
|
||||
an exception is thrown, <tt>delete[] p</tt> is called.</p>
|
||||
<h3>shared_array <a name="shared_array_operator[]">operator[]</a></h3>
|
||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
|
||||
stored pointer.</p>
|
||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
|
||||
@ -154,16 +166,24 @@ 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 at point of instantiation.
|
||||
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 at point of instantiation.
|
||||
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 at point of instantiation.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
|
||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation.
|
||||
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>
|
||||
|
@ -118,6 +118,8 @@ the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="shared_ptr_ctor">shared_ptr constructors</a></h3>
|
||||
<pre>explicit shared_ptr( T* p=0 );</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Constructs a <strong>shared_ptr</strong>, storing a copy of <tt>p</tt>, which
|
||||
must have been allocated via a C++ <tt>new</tt> expression or be 0. Afterwards, <strong>use_count()</strong>
|
||||
is 1 (even if p==0; see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>).</p>
|
||||
@ -128,6 +130,8 @@ template<typename Y>
|
||||
shared_ptr(const shared_ptr<Y>& r); // never throws
|
||||
template<typename Y>
|
||||
shared_ptr(std::auto_ptr<Y>& r);</pre>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Constructs a <strong>shared_ptr</strong>, as if by storing a copy of the
|
||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
|
||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
|
||||
@ -138,6 +142,8 @@ is <tt>std::bad_alloc</tt>. If an exception is thrown, that
|
||||
constructor has no effect.</p>
|
||||
<h3><a name="shared_ptr_~shared_ptr">shared_ptr destructor</a></h3>
|
||||
<pre>~shared_ptr();</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>If <strong>use_count()</strong> == 1, deletes the object pointed to by the
|
||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
|
||||
copies is decremented by 1. Note that in C++ <tt>delete</tt> on a pointer
|
||||
@ -149,6 +155,8 @@ template<typename Y>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r);
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(std::auto_ptr<Y>& r);</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
|
||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt> on
|
||||
@ -164,6 +172,8 @@ is <tt>std::bad_alloc</tt>. If an exception is thrown, the function
|
||||
has no effect.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_reset">reset</a></h3>
|
||||
<pre>void reset( T* p=0 );</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
|
||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
|
||||
remaining copies is decremented by 1. </p>
|
||||
@ -176,33 +186,46 @@ on a pointer with a value of 0 is harmless.</p>
|
||||
an exception is thrown, <tt>delete p</tt> is called.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3>
|
||||
<pre>T& operator*() const; // never throws</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation. See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_operator->">operator-></a> and <a name="shared_ptr_get">get</a></h3>
|
||||
<pre>T* operator->() const; // never throws
|
||||
T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is required be a complete type at point of instantiation of
|
||||
operator->(). See <a href="smart_ptr.htm#Common requirements">Common
|
||||
Requirements</a>.</p>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation of
|
||||
get(). 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 at point of instantiation.
|
||||
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 at point of instantiation.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
|
||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
|
||||
<p><b>T</b> is not required be a complete type at point of instantiation.
|
||||
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>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. Furthermore, use_count() may be even higher
|
||||
rather than a std::multiset, and thus does not contain duplicate entries. Furthermore, use_count() may be even higher
|
||||
at various times while push_back() and insert() container operations are performed.
|
||||
More complicated yet, the container operations may throw exceptions under a
|
||||
variety of circumstances. Without using a smart pointer, memory and
|
||||
exception management would be a nightmare.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->21 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13958" -->
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960" -->
|
||||
</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
|
||||
|
@ -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,25 @@ provided to verify correct operation.</p>
|
||||
<p>A page on <a href="smarttests.htm">Smart Pointer Timings</a> will be of
|
||||
interest to those curious about performance issues.</p>
|
||||
<h2><a name="Common requirements">Common requirements</a></h2>
|
||||
<p>These smart pointer classes have a template parameter, <tt>T</tt>, which
|
||||
<p>These smart pointer classes have a template parameter, <tt><b>T</b></tt>, which
|
||||
specifies the type of the object pointed to by the smart pointer. The
|
||||
behavior of all four classes is undefined if the destructor or operator delete
|
||||
for objects of type <tt>T</tt> throws exceptions.</p>
|
||||
for objects of type <tt><b>T</b></tt> throws 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 point of instantiation of all member functions.</p>
|
||||
<h3>Rationale</h3>
|
||||
<p>The requirements on <tt><b>T</b></tt> are carefully crafted to ensure safety
|
||||
yet allow handle-body (aka 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.</p>
|
||||
<h3>Example</h3>
|
||||
<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. 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>Exception safety</h2>
|
||||
<p>Several functions in these smart pointer classes are specified as having
|
||||
"no effect" or "no effect except such-and-such" if an
|
||||
@ -78,6 +93,10 @@ never throws</kbd>. </p>
|
||||
<p>Functions which destroy objects of the pointed to type are prohibited from
|
||||
throwing exceptions by the <a href="#Common requirements">Common requirements</a>.</p>
|
||||
<h2>History and acknowledgements</h2>
|
||||
<p>May, 2001. Vladimir Prus suggested requiring a complete type on
|
||||
destruction. Refinement evolved in discussions including Dave Abrahams,
|
||||
Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus,
|
||||
Shankar Sai, and others.</p>
|
||||
<p>November, 1999. Darin Adler provided operator ==, operator !=, and std::swap
|
||||
and std::less specializations for shared types.</p>
|
||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
|
||||
@ -125,7 +144,7 @@ implementation.</p>
|
||||
<p>See the Revision History section of the header for further contributors.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
|
||||
-->27 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14992"
|
||||
-->22 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15106"
|
||||
--></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
|
||||
|
Reference in New Issue
Block a user