mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-07-29 20:37:13 +02:00
New smart pointer documentation. Related clean-up of the smart pointer
library. Changing includes to include the new individual smart pointer headers. Replacing old smart pointer library with an include of the new smart pointer headers. Simplify ifdefs that involve the member templates macros now that BOOST_MSVC6_MEMBER_TEMPLATES is also guaranteed to bet set for platforms that have full member templates. [SVN r12647]
This commit is contained in:
105
compatibility.htm
Normal file
105
compatibility.htm
Normal file
@ -0,0 +1,105 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>Smart Pointer Changes</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Smart
|
||||
Pointer Changes</h1>
|
||||
|
||||
<p>The February 2002 change to the Boost smart pointers introduced a number
|
||||
of changes. Since the previous version of the smart pointers was in use for
|
||||
a long time, it's useful to have a detailed list of what changed from a library
|
||||
user's point of view.</p>
|
||||
|
||||
<p>Note that for compilers that don't support member templates well enough,
|
||||
a separate implementation is used that lacks many of the new features and is
|
||||
more like the old version.</p>
|
||||
|
||||
<h2>Features Requiring Code Changes to Take Advantage</h2>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The smart pointer class templates now each have their own header file.
|
||||
For compatibility, the
|
||||
<a href="../../boost/smart_ptr.hpp"><boost/smart_ptr.hpp></a>
|
||||
header now includes the headers for the four classic smart pointer class templates.</li>
|
||||
|
||||
<li>The <b>weak_ptr</b> template was added.</li>
|
||||
|
||||
<li>The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that the pointed-to object's
|
||||
destructor must be visible when instantiating the <b>shared_ptr</b> destructor.
|
||||
This makes it easier to have shared_ptr members in classes without explicit destructors.</li>
|
||||
|
||||
<li>A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.</li>
|
||||
|
||||
<li><b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are
|
||||
provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b> and
|
||||
<b>dynamic_cast</b> do for pointers.</li>
|
||||
|
||||
<li>The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,
|
||||
although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.
|
||||
Calling <b>reset</b> with a pointer to the object that's already owned by the
|
||||
<b>shared_ptr</b> results in undefined behavior
|
||||
(an assertion, or eventually a double-delete if assertions are off).</li>
|
||||
|
||||
<li>The <b>BOOST_SMART_PTR_CONVERSION</b> feature has been removed.</li>
|
||||
|
||||
<li><b>shared_ptr<void></b> is now allowed.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Features That Improve Robustness</h2>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The manipulation of use counts is now thread safe on Windows, Linux, and platforms
|
||||
that support pthreads. See the
|
||||
<a href="../../boost/detail/atomic_count.hpp"><boost/detail/atomic_count.hpp></a>
|
||||
file for details</li>
|
||||
|
||||
<li>The new shared_ptr will always delete the object using the pointer it was originally constructed with.
|
||||
This prevents subtle problems that could happen if the last <b>shared_ptr</b> was a pointer to a sub-object
|
||||
of a class that did not have a virtual destructor.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Implementation Details</h2>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Some bugs in the assignment operator implementations and in <b>reset</b>
|
||||
have been fixed by using the "copy and swap" idiom.</li>
|
||||
|
||||
<li>Assertions have been added to check preconditions of various functions;
|
||||
however, since these use the new
|
||||
<a href="../../boost/assert.hpp"><boost/assert.hpp></a>
|
||||
header, the assertions are disabled by default.</li>
|
||||
|
||||
<li>The partial specialization of <b>std::less</b> has been replaced by <b>operator<</b>
|
||||
overloads which accomplish the same thing without relying on undefined behavior.</li>
|
||||
|
||||
<li>The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>, which
|
||||
has many of the same advantages for generic programming but does not violate the C++ standard.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised 1 February 2002</p>
|
||||
|
||||
<p>Copyright 2002 Darin Adler.
|
||||
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"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -35,49 +35,49 @@ public:
|
||||
|
||||
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()
|
||||
~scoped_array() // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete [] ptr;
|
||||
}
|
||||
|
||||
void reset( T* p = 0 )
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
|
||||
if ( ptr != p )
|
||||
if (ptr != p)
|
||||
{
|
||||
delete [] ptr;
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
T& operator[](std::ptrdiff_t i) const // never throws
|
||||
T& operator[](std::ptrdiff_t i) const // never throws
|
||||
{
|
||||
BOOST_ASSERT(ptr != 0);
|
||||
BOOST_ASSERT(i >= 0);
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
T* get() const // never throws
|
||||
T* get() const // never throws
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void swap(scoped_array & rhs)
|
||||
void swap(scoped_array & b) // never throws
|
||||
{
|
||||
T * tmp = rhs.ptr;
|
||||
rhs.ptr = ptr;
|
||||
T * tmp = b.ptr;
|
||||
b.ptr = ptr;
|
||||
ptr = tmp;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b)
|
||||
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ namespace boost
|
||||
|
||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_ptr // noncopyable
|
||||
@ -34,57 +34,57 @@ public:
|
||||
|
||||
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()
|
||||
~scoped_ptr() // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
void reset( T* p = 0 )
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
|
||||
if ( ptr != p )
|
||||
if (ptr != p)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
T& operator*() const // never throws
|
||||
T & operator*() const // never throws
|
||||
{
|
||||
BOOST_ASSERT(ptr != 0);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
T* operator->() const // never throws
|
||||
T * operator->() const // never throws
|
||||
{
|
||||
BOOST_ASSERT(ptr != 0);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T* get() const // never throws
|
||||
T * get() const // never throws
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void swap(scoped_ptr & rhs)
|
||||
void swap(scoped_ptr & b) // never throws
|
||||
{
|
||||
T * tmp = rhs.ptr;
|
||||
rhs.ptr = ptr;
|
||||
T * tmp = b.ptr;
|
||||
b.ptr = ptr;
|
||||
ptr = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b)
|
||||
template<typename T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
|
||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
#ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
#include <boost/detail/shared_array_nmt.hpp>
|
||||
#else
|
||||
|
||||
@ -75,6 +75,11 @@ public:
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
template <typename D> void reset(T * p = 0, D d)
|
||||
{
|
||||
this_type(p, d).swap(*this);
|
||||
}
|
||||
|
||||
T & operator[] (std::ptrdiff_t i) const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
@ -87,16 +92,16 @@ public:
|
||||
return px;
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
bool unique() const // never throws
|
||||
{
|
||||
return pn.unique();
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
void swap(shared_array<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
@ -110,28 +115,28 @@ private:
|
||||
|
||||
}; // shared_array
|
||||
|
||||
template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b)
|
||||
template<typename T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b)
|
||||
template<typename T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b)
|
||||
template<typename T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||
{
|
||||
return std::less<T*>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<class T> void swap(shared_array<T> & a, shared_array<T> & b)
|
||||
template<typename T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES)
|
||||
#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
|
||||
#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
|
||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
#ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
#include <boost/detail/shared_ptr_nmt.hpp>
|
||||
#else
|
||||
|
||||
@ -44,7 +44,7 @@ namespace detail
|
||||
struct static_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
|
||||
template<class T> struct shared_ptr_traits
|
||||
template<typename T> struct shared_ptr_traits
|
||||
{
|
||||
typedef T & reference;
|
||||
};
|
||||
@ -108,10 +108,8 @@ public:
|
||||
template<typename Y>
|
||||
shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
if(px == 0) // need to allocate new counter -- the cast failed
|
||||
{
|
||||
if (px == 0) // need to allocate new counter -- the cast failed
|
||||
pn = detail::shared_count(static_cast<element_type *>(0), deleter());
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
@ -124,7 +122,7 @@ public:
|
||||
#endif
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr & operator=(shared_ptr<Y> const & r) // nothrow?
|
||||
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||
{
|
||||
px = r.px;
|
||||
pn = r.pn; // shared_count::op= doesn't throw
|
||||
@ -170,16 +168,16 @@ public:
|
||||
return px;
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
bool unique() const // never throws
|
||||
{
|
||||
return pn.unique();
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
void swap(shared_ptr<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
@ -204,39 +202,39 @@ private:
|
||||
|
||||
}; // shared_ptr
|
||||
|
||||
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||
template<typename T, typename U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||
template<typename T, typename U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
|
||||
template<typename T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
|
||||
{
|
||||
return std::less<T*>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, detail::static_cast_tag());
|
||||
}
|
||||
|
||||
template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, detail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||
template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<typename T, typename U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, detail::static_cast_tag());
|
||||
}
|
||||
|
||||
template<typename T, typename U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
|
||||
{
|
||||
return shared_ptr<T>(r, detail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
// get_pointer() enables boost::mem_fn to recognize shared_ptr
|
||||
|
||||
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||
template<typename T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
@ -247,6 +245,6 @@ template<class T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC_MEMBER_TEMPLATES)
|
||||
#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
|
||||
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
|
||||
|
@ -1,402 +1,9 @@
|
||||
// Boost smart_ptr.hpp header file -----------------------------------------//
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. 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
|
||||
// 6 Jul 01 Reorder shared_ptr code so VC++ 6 member templates work, allowing
|
||||
// polymorphic pointers to now work with that compiler (Gary Powell)
|
||||
// 21 May 01 Require complete type where incomplete type is unsafe.
|
||||
// (suggested by Vladimir Prus)
|
||||
// 21 May 01 operator= fails if operand transitively owned by *this, as in a
|
||||
// linked list (report by Ken Johnson, fix by Beman Dawes)
|
||||
// 21 Jan 01 Suppress some useless warnings with MSVC (David Abrahams)
|
||||
// 19 Oct 00 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
|
||||
// 24 Jul 00 Change throw() to // never throws. See lib guidelines
|
||||
// Exception-specification rationale. (Beman Dawes)
|
||||
// 22 Jun 00 Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
|
||||
// 1 Feb 00 Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
|
||||
// (Dave Abrahams)
|
||||
// 31 Dec 99 Condition tightened for no member template friend workaround
|
||||
// (Dave Abrahams)
|
||||
// 30 Dec 99 Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
|
||||
// (Dave Abrahams)
|
||||
// 30 Nov 99 added operator ==, operator !=, and std::swap and std::less
|
||||
// specializations for shared types (Darin Adler)
|
||||
// 11 Oct 99 replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
|
||||
// Bonnard), added shared_ptr workaround for no member template
|
||||
// friends (Matthew Langston)
|
||||
// 25 Sep 99 added shared_ptr::swap and shared_array::swap (Luis Coelho).
|
||||
// 20 Jul 99 changed name to smart_ptr.hpp, #include <boost/config.hpp>,
|
||||
// #include <boost/utility.hpp> and use boost::noncopyable
|
||||
// 17 May 99 remove scoped_array and shared_array operator*() as
|
||||
// unnecessary (Beman Dawes)
|
||||
// 14 May 99 reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
|
||||
// 13 May 99 remove certain throw() specifiers to avoid generated try/catch
|
||||
// code cost (Beman Dawes)
|
||||
// 11 May 99 get() added, conversion to T* placed in macro guard (Valentin
|
||||
// Bonnard, Dave Abrahams, and others argued for elimination
|
||||
// of the automatic conversion)
|
||||
// 28 Apr 99 #include <memory> fix (Valentin Bonnard)
|
||||
// 28 Apr 99 rename transfer() to share() for clarity (Dave Abrahams)
|
||||
// 28 Apr 99 remove unsafe shared_array template conversions(Valentin Bonnard)
|
||||
// 28 Apr 99 p(r) changed to p(r.px) for clarity (Dave Abrahams)
|
||||
// 21 Apr 99 reset() self assignment fix (Valentin Bonnard)
|
||||
// 21 Apr 99 dispose() provided to improve clarity (Valentin Bonnard)
|
||||
// 27 Apr 99 leak when new throws fixes (Dave Abrahams)
|
||||
// 21 Oct 98 initial Version (Greg Colvin/Beman Dawes)
|
||||
|
||||
#ifndef BOOST_SMART_PTR_HPP
|
||||
#define BOOST_SMART_PTR_HPP
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
#include <cstddef> // for std::size_t
|
||||
#include <memory> // for std::auto_ptr
|
||||
#include <algorithm> // for std::swap
|
||||
#include <boost/utility.hpp> // for boost::noncopyable, checked_delete, checked_array_delete
|
||||
#include <functional> // for std::less
|
||||
#include <boost/static_assert.hpp> // for BOOST_STATIC_ASSERT
|
||||
|
||||
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
// scoped_ptr --------------------------------------------------------------//
|
||||
|
||||
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
|
||||
// of the object pointed to, either on destruction of the scoped_ptr or via
|
||||
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
|
||||
// see shared_ptr (below) or std::auto_ptr if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_ptr : noncopyable {
|
||||
|
||||
T* ptr;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr( T* p=0 ) : ptr(p) {} // never throws
|
||||
~scoped_ptr() { checked_delete(ptr); }
|
||||
void reset( T* p=0 ) { if ( ptr != p ) { checked_delete(ptr); ptr = p; } }
|
||||
T& operator*() const { return *ptr; } // never throws
|
||||
T* operator->() const { return ptr; } // never throws
|
||||
T* get() const { return ptr; } // never throws
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const { return ptr; } // never throws
|
||||
#endif
|
||||
}; // scoped_ptr
|
||||
|
||||
// scoped_array ------------------------------------------------------------//
|
||||
|
||||
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
|
||||
// is guaranteed, either on destruction of the scoped_array or via an explicit
|
||||
// reset(). See shared_array or std::vector if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_array : noncopyable {
|
||||
|
||||
T* ptr;
|
||||
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_array( T* p=0 ) : ptr(p) {} // never throws
|
||||
~scoped_array() { checked_array_delete(ptr); }
|
||||
|
||||
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
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const { return ptr; } // never throws
|
||||
#else
|
||||
T& operator[](std::size_t i) const { return ptr[i]; } // never throws
|
||||
#endif
|
||||
}; // scoped_array
|
||||
|
||||
// shared_ptr --------------------------------------------------------------//
|
||||
|
||||
// An enhanced relative of scoped_ptr with reference counted copy semantics.
|
||||
// The object pointed to is deleted when the last shared_ptr pointing to it
|
||||
// is destroyed or reset.
|
||||
|
||||
template<typename T> class shared_ptr {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_ptr(T* p =0) : px(p) {
|
||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
||||
catch (...) { checked_delete(p); throw; }
|
||||
}
|
||||
|
||||
~shared_ptr() { dispose(); }
|
||||
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) || defined (BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
template<typename Y>
|
||||
shared_ptr(const shared_ptr<Y>& r) : px(r.px) { // never throws
|
||||
++*(pn = r.pn);
|
||||
}
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
template<typename Y>
|
||||
explicit shared_ptr(std::auto_ptr<Y>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r) {
|
||||
share(r.px,r.pn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(std::auto_ptr<Y>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { checked_delete(px); }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
pn = tmp;
|
||||
} // allocate new reference counter
|
||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
explicit shared_ptr(std::auto_ptr<T>& r) {
|
||||
pn = new long(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
|
||||
shared_ptr& operator=(std::auto_ptr<T>& r) {
|
||||
// code choice driven by guarantee of "no effect if new throws"
|
||||
if (*pn == 1) { checked_delete(px); }
|
||||
else { // allocate new reference counter
|
||||
long * tmp = new long(1); // may throw
|
||||
--*pn; // only decrement once danger of new throwing is past
|
||||
pn = tmp;
|
||||
} // allocate new reference counter
|
||||
px = r.release(); // fix: moved here so doesn't leak if new throws
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The assignment operator and the copy constructor must come after
|
||||
// the templated versions for MSVC6 to work. (Gary Powell)
|
||||
shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); } // never throws
|
||||
|
||||
shared_ptr& operator=(const shared_ptr& r) {
|
||||
share(r.px,r.pn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(T* p=0) {
|
||||
if ( px == p ) return; // fix: self-assignment safe
|
||||
if (--*pn == 0) { 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
|
||||
checked_delete(p);
|
||||
throw;
|
||||
} // catch
|
||||
} // allocate new reference counter
|
||||
*pn = 1;
|
||||
px = p;
|
||||
} // reset
|
||||
|
||||
T& operator*() const { return *px; } // never throws
|
||||
T* operator->() const { return px; } // never throws
|
||||
T* get() const { return px; } // never throws
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const { return px; } // never throws
|
||||
#endif
|
||||
|
||||
long use_count() const { return *pn; } // never throws
|
||||
bool unique() const { return *pn == 1; } // never throws
|
||||
|
||||
void swap(shared_ptr<T>& other) // never throws
|
||||
{ std::swap(px,other.px); std::swap(pn,other.pn); }
|
||||
|
||||
// Tasteless as this may seem, making all members public allows member templates
|
||||
// to work in the absence of member template friends. (Matthew Langston)
|
||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
||||
#if ( defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES) ) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
private:
|
||||
#endif
|
||||
|
||||
T* px; // contained pointer
|
||||
long* pn; // ptr to reference counter
|
||||
|
||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
|
||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
|
||||
template<typename Y> friend class shared_ptr;
|
||||
#endif
|
||||
|
||||
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
|
||||
++*rpn; // done before dispose() in case rpn transitively
|
||||
// dependent on *this (bug reported by Ken Johnson)
|
||||
dispose();
|
||||
px = rpx;
|
||||
pn = rpn;
|
||||
}
|
||||
} // share
|
||||
}; // shared_ptr
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
||||
{ return a.get() == b.get(); }
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
||||
{ return a.get() != b.get(); }
|
||||
|
||||
// shared_array ------------------------------------------------------------//
|
||||
|
||||
// shared_array extends shared_ptr to arrays.
|
||||
// The array pointed to is deleted when the last shared_array pointing to it
|
||||
// is destroyed or reset.
|
||||
|
||||
template<typename T> class shared_array {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_array(T* p =0) : px(p) {
|
||||
try { pn = new long(1); } // fix: prevent leak if new throws
|
||||
catch (...) { checked_array_delete(p); throw; }
|
||||
}
|
||||
|
||||
shared_array(const shared_array& r) : px(r.px) // never throws
|
||||
{ ++*(pn = r.pn); }
|
||||
|
||||
~shared_array() { dispose(); }
|
||||
|
||||
shared_array& operator=(const shared_array& r) {
|
||||
if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0
|
||||
++*r.pn; // done before dispose() in case r.pn transitively
|
||||
// dependent on *this (bug reported by Ken Johnson)
|
||||
dispose();
|
||||
px = r.px;
|
||||
pn = r.pn;
|
||||
}
|
||||
return *this;
|
||||
} // operator=
|
||||
|
||||
void reset(T* p=0) {
|
||||
if ( px == p ) return; // fix: self-assignment safe
|
||||
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
|
||||
checked_array_delete(p);
|
||||
throw;
|
||||
} // catch
|
||||
} // allocate new reference counter
|
||||
*pn = 1;
|
||||
px = p;
|
||||
} // reset
|
||||
|
||||
T* get() const { return px; } // never throws
|
||||
#ifdef BOOST_SMART_PTR_CONVERSION
|
||||
// get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
|
||||
operator T*() const { return px; } // never throws
|
||||
#else
|
||||
T& operator[](std::size_t i) const { return px[i]; } // never throws
|
||||
#endif
|
||||
|
||||
long use_count() const { return *pn; } // never throws
|
||||
bool unique() const { return *pn == 1; } // never throws
|
||||
|
||||
void swap(shared_array<T>& other) // never throws
|
||||
{ std::swap(px,other.px); std::swap(pn,other.pn); }
|
||||
|
||||
private:
|
||||
|
||||
T* px; // contained pointer
|
||||
long* pn; // ptr to reference counter
|
||||
|
||||
void dispose() { if (--*pn == 0) { checked_array_delete(px); delete pn; } }
|
||||
|
||||
}; // shared_array
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
|
||||
{ return a.get() == b.get(); }
|
||||
|
||||
template<typename T>
|
||||
inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
|
||||
{ return a.get() != b.get(); }
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// specializations for things in namespace std -----------------------------//
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
namespace std {
|
||||
|
||||
// Specialize std::swap to use the fast, non-throwing swap that's provided
|
||||
// as a member function instead of using the default algorithm which creates
|
||||
// a temporary and uses assignment.
|
||||
|
||||
template<typename T>
|
||||
inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
|
||||
{ a.swap(b); }
|
||||
|
||||
template<typename T>
|
||||
inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
|
||||
{ a.swap(b); }
|
||||
|
||||
// Specialize std::less so we can use shared pointers and arrays as keys in
|
||||
// associative collections.
|
||||
|
||||
// It's still a controversial question whether this is better than supplying
|
||||
// a full range of comparison operators (<, >, <=, >=).
|
||||
|
||||
template<typename T>
|
||||
struct less< boost::shared_ptr<T> >
|
||||
: binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
|
||||
{
|
||||
bool operator()(const boost::shared_ptr<T>& a,
|
||||
const boost::shared_ptr<T>& b) const
|
||||
{ return std::less<T*>()(a.get(),b.get()); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct less< boost::shared_array<T> >
|
||||
: binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
|
||||
{
|
||||
bool operator()(const boost::shared_array<T>& a,
|
||||
const boost::shared_array<T>& b) const
|
||||
{ return std::less<T*>()(a.get(),b.get()); }
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // BOOST_SMART_PTR_HPP
|
||||
|
||||
// For compatibility, this header includes the header for the four "classic"
|
||||
// smart pointer class templates.
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
|
@ -67,14 +67,20 @@ public:
|
||||
template<typename Y>
|
||||
weak_ptr(weak_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
if(px == 0) // need to allocate new counter -- the cast failed
|
||||
{
|
||||
if (px == 0) // need to allocate new counter -- the cast failed
|
||||
pn = detail::weak_count();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr & operator=(weak_ptr<Y> const & r) // nothrow?
|
||||
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
|
||||
{
|
||||
px = r.px;
|
||||
pn = r.pn;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||
{
|
||||
px = r.px;
|
||||
pn = r.pn;
|
||||
@ -86,11 +92,6 @@ public:
|
||||
this_type().swap(*this);
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return use_count() == 0? 0: px;
|
||||
@ -99,7 +100,6 @@ public:
|
||||
typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
|
||||
{
|
||||
T * p = get();
|
||||
|
||||
BOOST_ASSERT(p != 0);
|
||||
return *p;
|
||||
}
|
||||
@ -107,11 +107,15 @@ public:
|
||||
T * operator-> () const // never throws
|
||||
{
|
||||
T * p = get();
|
||||
|
||||
BOOST_ASSERT(p != 0);
|
||||
return p;
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return pn.use_count();
|
||||
}
|
||||
|
||||
void swap(weak_ptr<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
@ -149,6 +153,11 @@ template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const
|
||||
return std::less<T*>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
template<class T, class U> weak_ptr<T> shared_static_cast(weak_ptr<U> const & r)
|
||||
{
|
||||
return weak_ptr<T>(r, detail::static_cast_tag());
|
||||
@ -159,11 +168,6 @@ template<class T, class U> weak_ptr<T> shared_dynamic_cast(weak_ptr<U> const & r
|
||||
return weak_ptr<T>(r, detail::dynamic_cast_tag());
|
||||
}
|
||||
|
||||
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
// get_pointer() enables boost::mem_fn to recognize weak_ptr
|
||||
|
||||
template<class T> inline T * get_pointer(weak_ptr<T> const & p)
|
||||
|
31
index.htm
31
index.htm
@ -1,10 +1,10 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>Boost Smart Pointer Library</title>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
@ -19,19 +19,28 @@
|
||||
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More</big></font></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h1>Smart pointer library</h1>
|
||||
<p>The header smart_ptr.hpp provides four smart pointer classes. Smart
|
||||
pointers ease the management of memory dynamically allocated with C++ <strong>new</strong>
|
||||
expressions.
|
||||
<h1>Smart Pointer Library</h1>
|
||||
<p>The smart pointer library includes five smart pointer class templates. Smart
|
||||
pointers ease the management of memory dynamically allocated with C++ <b>new</b>
|
||||
expressions. In addition, <b>scoped_ptr</b> can ease the management of memory
|
||||
dynamically allocated in other ways.</p>
|
||||
<ul>
|
||||
<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/scoped_ptr.hpp">scoped_ptr.hpp</a>.</li>
|
||||
<li>Header <a href="../../boost/scoped_array.hpp">scoped_array.hpp</a>.</li>
|
||||
<li>Header <a href="../../boost/shared_ptr.hpp">shared_ptr.hpp</a>.</li>
|
||||
<li>Header <a href="../../boost/shared_array.hpp">shared_array.hpp</a>.</li>
|
||||
<li>Header <a href="../../boost/weak_ptr.hpp">weak_ptr.hpp</a>.</li>
|
||||
<li>Test program <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.</li>
|
||||
<li>Submitted by <a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/beman_dawes.html">Beman
|
||||
Dawes</a>.</li>
|
||||
<li>Originally submitted by
|
||||
<a href="../../people/greg_colvin.htm">Greg Colvin</a> and
|
||||
<a href="../../people/beman_dawes.html">Beman Dawes</a>,
|
||||
currently maintained by
|
||||
<a href="../../people/peter_dimov.htm">Peter Dimov</a> and
|
||||
<a href="../../people/darin_adler.htm">Darin Adler</a>.</li>
|
||||
</ul>
|
||||
<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>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="14885" -->.</p>
|
||||
|
||||
</body>
|
||||
|
||||
|
191
scoped_array.htm
191
scoped_array.htm
@ -1,101 +1,144 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>scoped_array</title>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
||||
<a name="scoped_array">scoped_array</a></h1>
|
||||
<p>Class <strong>scoped_array</strong> stores a pointer to a dynamically
|
||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
|
||||
expression.) The array pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <strong>scoped_array</strong>, or via an explicit <strong>scoped_array::reset()</strong>.</p>
|
||||
<p>Class<strong> scoped_array</strong> is a simple solution for simple
|
||||
needs. It supplies a basic "resource acquisition is
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86"><a name="scoped_array">scoped_array</a> class template</h1>
|
||||
|
||||
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically allocated
|
||||
array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
|
||||
expression.) The array pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
|
||||
|
||||
<p>The <b>scoped_array</b> template is a simple solution for simple
|
||||
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
|
||||
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_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
|
||||
|
||||
<p>Because <b>scoped_array</b> is so simple, in its usual implementation
|
||||
every operation is as fast as a built-in array pointer and it has no
|
||||
more space overhead that a built-in array pointer.</p>
|
||||
<p>It cannot be used in C++ Standard Library containers. See <a href="shared_array.htm"><strong>shared_array</strong></a>
|
||||
if <strong>scoped_array</strong> does not meet your needs.</p>
|
||||
<p>Class<strong> scoped_array</strong> cannot correctly hold a pointer to a
|
||||
single object. See <a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a>
|
||||
|
||||
<p>It cannot be used in C++ standard library containers.
|
||||
See <a href="shared_array.htm"><b>shared_array</b></a>
|
||||
if <b>scoped_array</b> does not meet your needs.</p>
|
||||
|
||||
<p>It cannot correctly hold a pointer to a single object.
|
||||
See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
|
||||
for that usage.</p>
|
||||
<p>A C++ Standard Library <strong>vector</strong> is a <strong> </strong>heavier duty alternative to a <strong>scoped_array</strong>.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2>Class scoped_array Synopsis</h2>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
|
||||
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is
|
||||
a bit heavier duty but far more flexible.
|
||||
A <b>boost::array</b> is an alternative that does not use dynamic allocation.</p>
|
||||
|
||||
public:
|
||||
typedef T <a href="#scoped_array_element_type">element_type</a>;
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object
|
||||
pointed to. <b>T</b> must meet the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
explicit <a href="#scoped_array_ctor">scoped_array</a>( T* p=0 ); // never throws
|
||||
<strong> </strong><a href="#scoped_array_~scoped_array">~scoped_array</a>();
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
void <a href="#scoped_array_reset">reset</a>( T* p=0 );
|
||||
<pre>namespace boost {
|
||||
|
||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws
|
||||
<a href="#~scoped_array">~scoped_array</a>(); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
|
||||
T & <a href="#operator[]">operator[]</a>(std::size_t i) const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(scoped_array & b); // never throws
|
||||
};
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(scoped_array<T> & a, scoped_array<T> & b); // never throws
|
||||
|
||||
T& <a href="#scoped_array_operator[]">operator[]</a>(std::size_t i) const; // never throws
|
||||
T* <a href="#scoped_array_get">get</a>() const; // never throws
|
||||
};
|
||||
}</pre>
|
||||
<h2>Class scoped_array Members</h2>
|
||||
<h3>scoped_array <a name="scoped_array_element_type">element_type</a></h3>
|
||||
|
||||
<h2>Members</h2>
|
||||
|
||||
<h3>
|
||||
<a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="scoped_array_ctor">scoped_array constructors</a></h3>
|
||||
<pre>explicit scoped_array( T* p=0 ); // never throws</pre>
|
||||
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
|
||||
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
|
||||
<pre>~scoped_array();</pre>
|
||||
<p>Deletes the array pointed to by the stored pointer. Note that in C++ <tt>delete</tt>[]
|
||||
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>
|
||||
|
||||
<h3><a name="ctor">constructors</a></h3>
|
||||
<pre>explicit scoped_array(T * p = 0); // never throws</pre>
|
||||
<p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must
|
||||
have been allocated via a C++ <b>new</b>[] expression or be 0.
|
||||
<b>T</b> is not required be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="~scoped_array">destructor</a></h3>
|
||||
<pre>~scoped_array(); // never throws</pre>
|
||||
<p>Deletes the array pointed to by the stored pointer.
|
||||
Note that <b>delete[]</b> on a pointer with a value of 0 is harmless.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted array's objects' destructors do not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(T * p = 0); // never throws</pre>
|
||||
<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>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>,
|
||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
|
||||
C++ <b>new[]</b> expression or be 0.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted array's objects' destructors do not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="operator[]">subscripting</a></h3>
|
||||
<pre>T & operator[](std::size_t i) const; // never throws</pre>
|
||||
<p>Returns a reference to element <b>i</b> of the array pointed to by the
|
||||
stored pointer.
|
||||
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
|
||||
or if <b>i</b> is less than 0 or is greater than or equal to the number of elements
|
||||
in the array.</p>
|
||||
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
|
||||
<pre>T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the stored pointer.</p>
|
||||
<h2>Class <a name="shared_array_example">scoped_array example</a></h2>
|
||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(scoped_array & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
|
||||
-->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964"
|
||||
-->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan-->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="13964"--></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
|
262
scoped_ptr.htm
262
scoped_ptr.htm
@ -1,152 +1,216 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>scoped_ptr</title>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
||||
<a name="scoped_ptr">scoped_ptr</a></h1>
|
||||
<p>Class <strong>scoped_ptr</strong> stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
|
||||
expression.) The object pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <strong>scoped_ptr</strong>, or via an explicit <strong>scoped_ptr::reset()</strong>.
|
||||
See <a href="#scoped_ptr_example">example</a>.</p>
|
||||
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
|
||||
needs. It supplies a basic "resource acquisition is
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86"><a name="scoped_ptr">scoped_ptr</a> class template</h1>
|
||||
|
||||
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <b>new</b>
|
||||
expression.) The object pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <b>scoped_ptr</b>, or via an explicit <b>reset</b>.
|
||||
See the <a href="#example">example</a>.</p>
|
||||
|
||||
<p>The <b>scoped_ptr</b> template is a simple solution for simple
|
||||
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.
|
||||
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
|
||||
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
|
||||
|
||||
<p>Because <b>scoped_ptr</b> is simple, in its usual implementation
|
||||
every operation is as fast as for a built-in pointer and it has no more space overhead
|
||||
that a built-in pointer. (Because of the "complete type"
|
||||
requirement for delete and reset members, they may have one additional function
|
||||
call overhead in certain idioms. See <a href="#Handle/Body">Handle/Body
|
||||
Idiom</a>.) </p>
|
||||
<p>Class<strong> scoped_ptr</strong> cannot be used in C++ Standard Library containers. See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
|
||||
or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p>
|
||||
<p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="scoped_array.htm"><strong>scoped_array</strong></a>
|
||||
that a built-in pointer.</p>
|
||||
|
||||
<p>It cannot be used in C++ Standard Library containers.
|
||||
See <a href="shared_ptr.htm"><b>shared_ptr</b></a>
|
||||
or <b>std::auto_ptr</b> if <b>scoped_ptr</b> does not meet your needs.</p>
|
||||
|
||||
<p>It cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a>
|
||||
for that usage.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
|
||||
requirements</a>.</p>
|
||||
<h2>Class scoped_ptr Synopsis</h2>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object
|
||||
pointed to. <b>T</b> must meet the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
public:
|
||||
typedef T <a href="#scoped_ptr_element_type">element_type</a>;
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
explicit <a href="#scoped_ptr_ctor">scoped_ptr</a>( T* p=0 ); // never throws
|
||||
<strong> </strong><a href="#scoped_ptr_~scoped_ptr">~scoped_ptr</a>();
|
||||
<pre>namespace boost {
|
||||
|
||||
void <a href="#scoped_ptr_reset">reset</a>( T* p=0 );
|
||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws
|
||||
<a href="#~scoped_ptr">~scoped_ptr</a>(); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(scoped_ptr & b); // never throws
|
||||
};
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws
|
||||
|
||||
T& <a href="#scoped_ptr_operator*">operator*</a>() const; // never throws
|
||||
T* <a href="#scoped_ptr_operator->">operator-></a>() const; // never throws
|
||||
T* <a href="#scoped_ptr_get">get</a>() const; // never throws
|
||||
};
|
||||
}</pre>
|
||||
<h2>Class scoped_ptr Members</h2>
|
||||
<h3>scoped_ptr <a name="scoped_ptr_element_type">element_type</a></h3>
|
||||
|
||||
<h2>Members</h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
|
||||
<pre>explicit scoped_ptr( T* p=0 ); // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must
|
||||
have been allocated via a C++ <tt>new</tt> expression or be 0.</p>
|
||||
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
|
||||
<pre>~scoped_ptr();</pre>
|
||||
<p>Deletes the object pointed to by the stored pointer. Note that in C++, <tt>delete</tt>
|
||||
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>
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
<pre>explicit scoped_ptr(T * p = 0); // never throws</pre>
|
||||
<p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must
|
||||
have been allocated via a C++ <b>new</b> expression or be 0.
|
||||
<b>T</b> is not required be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="~scoped_ptr">destructor</a></h3>
|
||||
<pre>~scoped_ptr(); // never throws</pre>
|
||||
<p>Deletes the object pointed to by the stored pointer.
|
||||
Note that <b>delete</b> on a pointer with a value of 0 is harmless.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted object's destructor does not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
<pre>void reset(T * p = 0); // never throws</pre>
|
||||
<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>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 not required by get() be a complete type. See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Both return the stored pointer.</p>
|
||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
|
||||
<pre>#include <iostream>
|
||||
#include <boost/smart_ptr.h>
|
||||
C++ <b>new</b> expression or be 0.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted object's destructor does not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } };
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.</p>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(scoped_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<h2><a name="example">Example</a></h2>
|
||||
|
||||
<p>Here's an example that uses <b>scoped_ptr</b>.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>#include <boost/scoped_ptr.hpp>
|
||||
#include <iostream>
|
||||
|
||||
struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
|
||||
|
||||
class MyClass {
|
||||
boost::scoped_ptr<int> ptr;
|
||||
public:
|
||||
MyClass() : ptr(new int) { *ptr = 0; }
|
||||
int add_one() { return ++*ptr; }
|
||||
};
|
||||
};
|
||||
|
||||
void main() {
|
||||
void main()
|
||||
{
|
||||
boost::scoped_ptr<Shoe> x(new Shoe);
|
||||
MyClass my_instance;
|
||||
std::cout << my_instance.add_one() << std::endl;
|
||||
std::cout << my_instance.add_one() << std::endl;
|
||||
}</pre>
|
||||
<p>The example program produces the beginning of a child's nursery rhyme as
|
||||
output:</p>
|
||||
std::cout << my_instance.add_one() << '\n';
|
||||
std::cout << my_instance.add_one() << '\n';
|
||||
}</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>The example program produces the beginning of a child's nursery rhyme:</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>1
|
||||
2
|
||||
Buckle my shoe</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Rationale</h2>
|
||||
<p>The primary reason to use <b> scoped_ptr</b> rather than <b> auto_ptr</b> is to let readers
|
||||
of your code know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer
|
||||
ownership.</p>
|
||||
<p>A secondary reason to use <b> scoped_ptr</b> is to prevent a later maintenance programmer from adding a function that actually transfers
|
||||
ownership by returning the <b> auto_ptr</b> (because the maintenance programmer saw
|
||||
<b>auto_ptr</b>, and assumed ownership could safely be transferred.) </p>
|
||||
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b> bool</b> is usually
|
||||
just an <b>int</b>. Indeed, some argued against including <b> bool</b> in the
|
||||
C++ standard because of that. But by coding <b> bool</b> rather than <b> int</b>, you tell your readers
|
||||
what your intent is. Same with <b> scoped_ptr</b> - you are signaling intent.</p>
|
||||
<p>It has been suggested that <b>boost::scoped_ptr<T></b> is equivalent to
|
||||
<b>std::auto_ptr<T> const</b>. Ed Brey pointed out, however, that
|
||||
reset() will not work on a <b>std::auto_ptr<T> const.</b></p>
|
||||
|
||||
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to let readers
|
||||
of your code know that you intend "resource acquisition is initialization" to be applied only
|
||||
for the current scope, and have no intent to transfer ownership.</p>
|
||||
|
||||
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance programmer
|
||||
from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
|
||||
because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership could safely
|
||||
be transferred.</p>
|
||||
|
||||
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b> is usually
|
||||
just an <b>int</b>. Indeed, some argued against including <b>bool</b> in the
|
||||
C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>, you tell your readers
|
||||
what your intent is. Same with <b>scoped_ptr</b>; by using it you are signaling intent.</p>
|
||||
|
||||
<p>It has been suggested that <b>scoped_ptr<T></b> is equivalent to
|
||||
<b>std::auto_ptr<T> const</b>. Ed Brey pointed out, however, that
|
||||
<b>reset</b> will not work on a <b>std::auto_ptr<T> const.</b></p>
|
||||
|
||||
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
|
||||
|
||||
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also
|
||||
called pimpl) idiom which avoids exposing the body (implementation) in the header
|
||||
file.</p>
|
||||
|
||||
<p>The <a href="scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
|
||||
sample program includes a header file, <a href="scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
|
||||
which uses a <b>scoped_ptr<></b> to an incomplete type to hide the
|
||||
implementation. The
|
||||
instantiation of member functions which require a complete type occurs in the <a href="scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
|
||||
implementation. 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>
|
||||
|
||||
<h2>Frequently Asked Questions</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
|
||||
<b>A</b>. Because the point of <b>scoped_ptr</b> is to signal intent, not
|
||||
to transfer ownership. Use <b>std::auto_ptr</b> if ownership transfer is
|
||||
required.</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110" --></p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="15110" --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Boost scoped_ptr_example header file ------------------------------------//
|
||||
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
// The point of this example is to prove that even though
|
||||
// example::implementation is an incomplete type in translation units using
|
||||
|
351
shared_array.htm
351
shared_array.htm
@ -1,188 +1,223 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>shared_array</title>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
||||
<a name="shared_array">shared_array</a></h1>
|
||||
<p>Class <strong>shared_array</strong> stores a pointer to a dynamically
|
||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
|
||||
expression.) The array pointed to is guaranteed to be deleted,
|
||||
either on destruction of the <strong>shared_array</strong>, on <strong>shared_array::operator=()</strong>,
|
||||
or via an explicit <strong>shared_array::reset()</strong>. See <a href="#shared_array_example">example</a>.</p>
|
||||
<p>Class<strong> shared_array</strong> meets the <strong>CopyConstuctible</strong>
|
||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
|
||||
can be used in C++ Standard Library containers. A specialization of std::
|
||||
less< > for boost::shared_ptr<Y> is supplied so that <strong>
|
||||
shared_array</strong> works by default for Standard Library's Associative
|
||||
Container Compare template parameter. For compilers not supporting partial
|
||||
specialization, the user must explicitly pass the less<> functor.</p>
|
||||
<p>Class<strong> shared_array</strong> cannot correctly hold a pointer to a
|
||||
single object. See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_array class template</h1>
|
||||
|
||||
<p>The <b>shared_array</b> class template stores a pointer to a dynamically allocated
|
||||
array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
|
||||
expression.) The object pointed to is guaranteed to be deleted when
|
||||
the last <b>shared_array</b> pointing to it is destroyed or reset.</p>
|
||||
|
||||
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b>
|
||||
and <b>Assignable</b> requirements of the C++ Standard Library, and so
|
||||
can be used in standard library containers. Comparison operators
|
||||
are supplied so that <b>shared_array</b> works with
|
||||
the standard library's associative containers.</p>
|
||||
|
||||
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="shared_ptr.htm"><b>shared_ptr</b></a>
|
||||
for that usage.</p>
|
||||
<p>Class<strong> shared_array</strong> will not work correctly with cyclic data
|
||||
structures. For example, if main() holds a shared_array pointing to array A,
|
||||
which directly or indirectly holds a shared_array pointing back to array A, then
|
||||
array A's use_count() will be 2, and destruction of the main() shared_array will
|
||||
leave array A dangling with a use_count() of 1.</p>
|
||||
<p>A C++ Standard Library <strong>vector</strong> is <strong> </strong>a <strong>
|
||||
</strong>heavier duty alternative to a <strong>shared_array</strong>.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
||||
requirements</a>.</p>
|
||||
<h2>Class shared_array Synopsis</h2>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class shared_array {
|
||||
<p>Because the implementation uses reference counting, <b>shared_array</b> will not work
|
||||
correctly with cyclic data structures. For example, if <b>main()</b> holds a <b>shared_array</b>
|
||||
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
|
||||
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
|
||||
will leave <b>A</b> dangling with a use count of 1.</p>
|
||||
|
||||
public:
|
||||
typedef T <a href="#shared_array_element_type">element_type</a>;
|
||||
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b> that is
|
||||
a bit heavier duty but far more flexible.</p>
|
||||
|
||||
explicit <a href="#shared_array_ctor">shared_array</a>( T* p=0 );
|
||||
<a href="#shared_array_ctor">shared_array</a>( const shared_array& ); // never throws
|
||||
<strong> </strong><a href="#shared_array_~shared_array">~shared_array</a>();
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object
|
||||
pointed to. <b>T</b> must meet the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
shared_array& <a href="#shared_array_operator=">operator=</a>( const shared_array& ); // never throws
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
void <a href="#shared_array_reset">reset</a>( T* p=0 );
|
||||
<pre>namespace boost {
|
||||
|
||||
T& <a href="#shared_array_operator[]">operator[]</a>(std::size_t i) const; // never throws
|
||||
T* <a href="#shared_array_get">get</a>() const; // never throws
|
||||
template<typename T> class shared_array {
|
||||
|
||||
long <a href="#shared_array_use_count">use_count</a>() const; // never throws
|
||||
bool <a href="#shared_array_unique">unique</a>() const; // never throws
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
void <a href="#shared_array_swap">swap</a>( shared_array<T>& other ) throw()
|
||||
};
|
||||
explicit <a href="#constructors">shared_array</a>(T * p = 0);
|
||||
template<typename D> <a href="#constructors">shared_array</a>(T * p, D d);
|
||||
<a href="#destructor">~shared_array</a>(); // never throws
|
||||
|
||||
template<typename T>
|
||||
inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
|
||||
{ return a.get() == b.get(); }
|
||||
<a href="#constructors">shared_array</a>(shared_array const & r); // never throws
|
||||
|
||||
template<typename T>
|
||||
inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
|
||||
{ return a.get() != b.get(); }
|
||||
}</pre>
|
||||
<pre>namespace std {
|
||||
shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
|
||||
|
||||
template<typename T>
|
||||
inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
|
||||
{ a.swap(b); }
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
template<typename D> void <a href="#reset">reset</a>(T * p, D d); // never throws
|
||||
|
||||
template<typename T>
|
||||
struct less< boost::shared_array<T> >
|
||||
: binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
|
||||
{
|
||||
bool operator()(const boost::shared_array<T>& a,
|
||||
const boost::shared_array<T>& b) const
|
||||
{ return less<T*>()(a.get(),b.get()); }
|
||||
T & <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
bool <a href="#unique">unique</a>() const; // never throws
|
||||
long <a href="#use_count">use_count</a>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(shared_array<T> & b); // never throws
|
||||
};
|
||||
|
||||
} // namespace std </pre>
|
||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
|
||||
as a member function instead of using the default algorithm which creates a
|
||||
temporary and uses assignment.<br>
|
||||
<br>
|
||||
Specialization of std::less allows use of shared arrays as keys in C++
|
||||
Standard Library associative collections.<br>
|
||||
<br>
|
||||
The std::less specializations use std::less<T*> to perform the
|
||||
comparison. This insures that pointers are handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).<br>
|
||||
<br>
|
||||
It's still a controversial question whether supplying only std::less is better
|
||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
|
||||
<p>The current implementation does not supply the specializations if the macro
|
||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
|
||||
<h2>Class shared_array Members</h2>
|
||||
<h3>shared_array <a name="shared_array_element_type">element_type</a></h3>
|
||||
template<typename T>
|
||||
bool <a href="#operator==">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#operator!=">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#operator<">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(shared_array<T> & a, shared_array<T> & b); // never throws
|
||||
|
||||
}</pre>
|
||||
|
||||
<h2>Members</h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<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>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>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>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
|
||||
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>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
|
||||
pointer with a value of 0 is harmless.</p>
|
||||
<p>Then replaces the contents of <strong>this</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>shared_array <a name="shared_array_reset">reset</a></h3>
|
||||
<pre>void reset( T* p=0 );</pre>
|
||||
<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 pointer with a value of 0 is harmless.</p>
|
||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
|
||||
of <strong>p</strong>, 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_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>
|
||||
<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>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>,
|
||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
|
||||
<pre>explicit shared_array(T * p = 0);</pre>
|
||||
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which
|
||||
must be a pointer to an array that was allocated via a C++ <b>new[]</b> expression or be 0.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">~shared_array</a>).
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>delete[] p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> shared_array(T * p, D d);</pre>
|
||||
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1.
|
||||
<b>D</b>'s copy constructor must not throw.
|
||||
When the the time comes to delete the array pointed to by <b>p</b>, the object
|
||||
<b>d</b> is used in the statement <b>d(p)</b>. Invoking the object <b>d</b> with
|
||||
parameter <b>p</b> in this way must not throw.
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
|
||||
<pre>shared_array(shared_array const & r); // never throws</pre>
|
||||
<p>Constructs a <b>shared_array</b>, as if by storing a copy of the
|
||||
pointer stored in <b>r</b>. Afterwards, the <a href="#use_count">use count</a>
|
||||
for all copies is 1 more than the initial use count.</p>
|
||||
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
|
||||
<pre>~shared_array(); // never throws</pre>
|
||||
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
|
||||
deletes the array pointed to by the stored pointer.
|
||||
Note that <b>delete[]</b> on a pointer with a value of 0 is harmless.
|
||||
<b>T</b> need not be a complete type.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted object's destructor does not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="operator=">assignment</a></h3>
|
||||
|
||||
<pre>shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws</pre>
|
||||
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_array</b> with the new one, destroying the replaced object.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
|
||||
<pre>void reset(T * p = 0);</pre>
|
||||
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_array</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, <b>delete[] p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> void reset(T * p, D d);</pre>
|
||||
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_array</b> with the new one, destroying the replaced object.
|
||||
<b>D</b>'s copy constructor must not throw.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
|
||||
<h3><a name="indirection">indexing</a></h3>
|
||||
<pre>T & operator[](std::size_t i) const; // never throws</pre>
|
||||
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored pointer.
|
||||
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
|
||||
or if <b>i</b> is less than 0 or is greater than or equal to the number of elements
|
||||
in the array.</p>
|
||||
<h3>shared_array <a name="shared_array_get">get</a></h3>
|
||||
<pre>T* get() const; // never throws</pre>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the stored pointer.</p>
|
||||
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
|
||||
<p><tt>long use_count() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
|
||||
stored pointer.</p>
|
||||
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
|
||||
<p><tt>bool unique() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
|
||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
||||
<h2>Class <a name="shared_array_example">shared_array example</a></h2>
|
||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="unique">unique</a></h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<p>Returns true if no other <b>shared_array</b> is sharing ownership of
|
||||
the stored pointer, false otherwise.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_array</b> objects sharing ownership of the
|
||||
stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>shared_array</b> that do not use an explicit reference
|
||||
count, it might be removed from some future version. Thus it should
|
||||
be used for debugging purposes only, and not production code.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T>
|
||||
bool <a href="#operator==">operator==</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#operator!=">operator!=</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws
|
||||
template<typename T>
|
||||
bool <a href="#operator<">operator<</a>(shared_array<T> const & a, shared_array<T> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>shared_array</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>.
|
||||
The implementation uses std::less<T*> to perform the
|
||||
comparison. This ensures that the comparison is handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).</p>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
void swap(shared_array<T> & a, shared_array<T> & b) // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->24 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13964" -->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||
modify, sell and distribute this document is granted provided this copyright
|
||||
notice appears in all copies. This document is provided "as is"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
|
506
shared_ptr.htm
506
shared_ptr.htm
@ -1,284 +1,356 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>shared_ptr</title>
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1>
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
|
||||
<a name="shared_ptr">shared_ptr</a></h1>
|
||||
<p><a href="#Introduction">Introduction<br>
|
||||
Synopsis</a><br>
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">shared_ptr class template</h1>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#shared_ptr_example">Example</a><br>
|
||||
<a href="#functions">Free Functions</a><br>
|
||||
<a href="#example">Example</a><br>
|
||||
<a href="#Handle/Body">Handle/Body Idiom</a><br>
|
||||
<a href="#FAQ">Frequently Asked Questions</a><br>
|
||||
<a href="smarttests.htm">Smart Pointer Timings</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
<p>Class <strong>shared_ptr</strong> stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
|
||||
expression.) The object pointed to is guaranteed to be deleted when
|
||||
the last <strong>shared_ptr</strong> pointing to it is deleted or reset.
|
||||
See <a href="#shared_ptr_example">example</a>.</p>
|
||||
<p>Class<strong> shared_ptr</strong> meets the <strong>CopyConstuctible</strong>
|
||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
|
||||
can be used in C++ Standard Library containers. A specialization of std::
|
||||
less< > for boost::shared_ptr<Y> is supplied so that <strong>
|
||||
shared_ptr</strong> works by default for Standard Library's Associative
|
||||
Container Compare template parameter. For compilers not supporting partial
|
||||
specialization, the user must explicitly pass the less<> functor.</p>
|
||||
<p>Class<strong> shared_ptr</strong> cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="shared_array.htm"><strong>shared_array</strong></a>
|
||||
|
||||
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
|
||||
object. (Dynamically allocated objects are allocated with the C++ <b>new</b>
|
||||
expression.) The object pointed to is guaranteed to be deleted when
|
||||
the last <b>shared_ptr</b> pointing to it is destroyed or reset.
|
||||
See the <a href="#example">example</a>.</p>
|
||||
|
||||
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b>
|
||||
and <b>Assignable</b> requirements of the C++ Standard Library, and so
|
||||
can be used in standard library containers. Comparison operators
|
||||
are supplied so that <b>shared_ptr</b> works with
|
||||
the standard library's associative containers.</p>
|
||||
|
||||
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a
|
||||
dynamically allocated array. See <a href="shared_array.htm"><b>shared_array</b></a>
|
||||
for that usage.</p>
|
||||
<p>Class<strong> shared_ptr</strong> will not work correctly with cyclic data
|
||||
structures. For example, if main() holds a shared_ptr to object A, which
|
||||
directly or indirectly holds a shared_ptr back to object A, then object A's
|
||||
use_count() will be 2, and destruction of the main() shared_ptr will leave
|
||||
object A dangling with a use_count() of 1.</p>
|
||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
|
||||
pointed to. <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
|
||||
requirements</a>.</p>
|
||||
<h2>Class shared_ptr <a name="Synopsis"> Synopsis</a></h2>
|
||||
<pre>#include <<a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>>
|
||||
namespace boost {
|
||||
|
||||
template<typename T> class shared_ptr {
|
||||
<p>Because the implementation uses reference counting, <b>shared_ptr</b> will not work
|
||||
correctly with cyclic data structures. For example, if <b>main()</b> holds a <b>shared_ptr</b>
|
||||
to <b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
|
||||
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b>
|
||||
will leave <b>A</b> dangling with a use count of 1.</p>
|
||||
|
||||
public:
|
||||
typedef T <a href="#shared_ptr_element_type">element_type</a>;
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object
|
||||
pointed to. <b>T</b> must meet the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.
|
||||
<b>T</b> may be <b>void</b>, but in that case, either an explicit delete
|
||||
function must be passed in, or the pointed-to object must have a trivial destructor.</p>
|
||||
|
||||
explicit <a href="#shared_ptr_ctor">shared_ptr</a>( T* p=0 );
|
||||
<strong> </strong><a href="#shared_ptr_~shared_ptr">~shared_ptr</a>();
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<a href="#shared_ptr_ctor">shared_ptr</a>( const shared_ptr& );
|
||||
template<typename Y>
|
||||
<a href="#shared_ptr_ctor">shared_ptr</a>(const shared_ptr<Y>& r); // never throws
|
||||
template<typename Y>
|
||||
<a href="#shared_ptr_ctor">shared_ptr</a>(std::auto_ptr<Y>& r);
|
||||
<pre>namespace boost {
|
||||
|
||||
shared_ptr& <a href="#shared_ptr_operator=">operator=</a>( const shared_ptr& ); // never throws
|
||||
template<typename Y>
|
||||
shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(const shared_ptr<Y>& r); // never throws
|
||||
template<typename Y>
|
||||
shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(std::auto_ptr<Y>& r);
|
||||
template<typename T> class shared_ptr {
|
||||
|
||||
void <a href="#shared_ptr_reset">reset</a>( T* p=0 );
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
T& <a href="#shared_ptr_operator*">operator*</a>() const; // never throws
|
||||
T* <a href="#shared_ptr_operator->">operator-></a>() const; // never throws
|
||||
T* <a href="#shared_ptr_get">get</a>() const; // never throws
|
||||
explicit <a href="#constructors">shared_ptr</a>(T * p = 0);
|
||||
template<typename D> <a href="#constructors">shared_ptr</a>(T * p, D d);
|
||||
<a href="#destructor">~shared_ptr</a>(); // never throws
|
||||
|
||||
long <a href="#shared_ptr_use_count">use_count</a>() const; // never throws
|
||||
bool <a href="#shared_ptr_unique">unique</a>() const; // never throws
|
||||
<a href="#constructors">shared_ptr</a>(shared_ptr const & r); // never throws
|
||||
template<typename Y> <a href="#constructors">shared_ptr</a>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> <a href="#constructors">shared_ptr</a>(std::auto_ptr<Y> & r);
|
||||
|
||||
void <a href="#shared_ptr_swap">swap</a>( shared_ptr<T>& other ) throw()
|
||||
};
|
||||
shared_ptr & <a href="#assignment">operator=</a>(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(std::auto_ptr<Y> & r);
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
||||
{ return a.get() == b.get(); }
|
||||
void <a href="#reset">reset</a>(T * p = 0); // never throws
|
||||
template<typename D> void <a href="#reset">reset</a>(T * p, D d); // never throws
|
||||
|
||||
template<typename T, typename U>
|
||||
inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
|
||||
{ return a.get() != b.get(); }
|
||||
}</pre>
|
||||
<pre>namespace std {
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
template<typename T>
|
||||
inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
|
||||
{ a.swap(b); }
|
||||
bool <a href="#unique">unique</a>() const; // never throws
|
||||
long <a href="#use_count">use_count</a>() const; // never throws
|
||||
|
||||
template<typename T>
|
||||
struct less< boost::shared_ptr<T> >
|
||||
: binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
|
||||
{
|
||||
bool operator()(const boost::shared_ptr<T>& a,
|
||||
const boost::shared_ptr<T>& b) const
|
||||
{ return less<T*>()(a.get(),b.get()); }
|
||||
void <a href="#swap">swap</a>(shared_ptr<T> & b); // never throws
|
||||
};
|
||||
|
||||
} // namespace std </pre>
|
||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
|
||||
as a member function instead of using the default algorithm which creates a
|
||||
temporary and uses assignment.<br>
|
||||
<br>
|
||||
Specialization of std::less allows use of shared pointers as keys in C++
|
||||
Standard Library associative collections.<br>
|
||||
<br>
|
||||
The std::less specializations use std::less<T*> to perform the
|
||||
comparison. This insures that pointers are handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).<br>
|
||||
<br>
|
||||
It's still a controversial question whether supplying only std::less is better
|
||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
|
||||
<p>The current implementation does not supply the specializations if the macro
|
||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
|
||||
<p>The current implementation does not supply the member template functions if
|
||||
the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
|
||||
<h2>Class shared_ptr <a name="Members"> Members</a></h2>
|
||||
<h3>shared_ptr <a name="shared_ptr_element_type">element_type</a></h3>
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator==">operator==</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator!=">operator!=</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(shared_ptr<T> & a, shared_ptr<T> & b); // never throws
|
||||
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr<U> const & r); // never throws
|
||||
template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr<U> const & r);
|
||||
|
||||
}</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<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>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>
|
||||
<p>The only exception which may be thrown by this constructor is <tt>std::bad_alloc</tt>.
|
||||
If an exception is thrown, <tt>delete p</tt> is called.</p>
|
||||
<pre>shared_ptr( const shared_ptr& r); // never throws
|
||||
template<typename Y>
|
||||
shared_ptr(const shared_ptr<Y>& r); // never throws
|
||||
template<typename Y>
|
||||
shared_ptr(std::auto_ptr<Y>& r);</pre>
|
||||
<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
|
||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
|
||||
is called.</p>
|
||||
<p>The only exception which may be thrown by the constructor from <strong>auto_ptr</strong>
|
||||
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>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
|
||||
with a value of 0 is harmless.</p>
|
||||
<p>Does not throw exceptions.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_operator=">operator=</a></h3>
|
||||
<pre>shared_ptr& operator=( const shared_ptr& r);
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r);
|
||||
template<typename Y>
|
||||
shared_ptr& operator=(std::auto_ptr<Y>& r);</pre>
|
||||
<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
|
||||
a pointer with a value of 0 is harmless.</p>
|
||||
<p>Then replaces the contents of <strong>this</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
|
||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
|
||||
is called.</p>
|
||||
<p>The first two forms of <tt>operator=</tt> above do not throw exceptions.</p>
|
||||
<p>The only exception which may be thrown by the <strong>auto_ptr</strong> form
|
||||
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>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>
|
||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
|
||||
of <strong>p</strong>, 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>). Note that in C++ <tt>delete</tt>
|
||||
on a pointer with a value of 0 is harmless.</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>
|
||||
<h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3>
|
||||
<pre>T& operator*() const; // never throws</pre>
|
||||
<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 not required by get() to be a complete type . See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Both return the stored pointer.</p>
|
||||
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
|
||||
<p><tt>long use_count() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
|
||||
stored pointer.</p>
|
||||
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
|
||||
<p><tt>bool unique() const; // never throws</tt></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Returns <strong>use_count()</strong> == 1.</p>
|
||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
|
||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
|
||||
<p><b>T</b> is not required be a complete type.
|
||||
See <a href="smart_ptr.htm#Common requirements">Common Requirements</a>.</p>
|
||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
|
||||
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
|
||||
<p>See <a href="shared_ptr_example.cpp"> shared_ptr_example.cpp</a> for a complete example program.</p>
|
||||
<p>This program builds a std::vector and std::set of FooPtr's.</p>
|
||||
<p>Note that after the two containers have been populated, some of the FooPtr objects
|
||||
will have use_count()==1 rather than use_count()==2, since foo_set is a std::set
|
||||
rather than a std::multiset, and thus does not contain duplicate entries. Furthermore, use_count() may be even higher
|
||||
at various times while push_back() and insert() container operations are performed.
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
|
||||
<pre>explicit shared_ptr(T * p = 0);</pre>
|
||||
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b>, which
|
||||
must be a pointer to an object that was allocated via a C++ <b>new</b> expression or be 0.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">~shared_ptr</a>).
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>delete p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> shared_ptr(T * p, D d);</pre>
|
||||
<p>Constructs a <b>shared_ptr</b>, storing a copy of <b>p</b> and of <b>d</b>.
|
||||
Afterwards, the <a href="#use_count">use count</a> is 1.
|
||||
<b>D</b>'s copy constructor must not throw.
|
||||
When the the time comes to delete the object pointed to by <b>p</b>, the object
|
||||
<b>d</b> is used in the statement <b>d(p)</b>. Invoking the object <b>d</b> with
|
||||
parameter <b>p</b> in this way must not throw.
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
|
||||
<pre>shared_ptr(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr(std::auto_ptr<Y> & r);</pre>
|
||||
<p>Constructs a <b>shared_ptr</b>, as if by storing a copy of the
|
||||
pointer stored in <b>r</b>. Afterwards, the <a href="#use_count">use count</a>
|
||||
for all copies is 1 more than the initial use count, or 1
|
||||
in the <b>auto_ptr</b> case. In the <b>auto_ptr</b> case, <b>r.release()</b>
|
||||
is called.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>,
|
||||
which may be thrown during construction from <b>auto_ptr</b>.
|
||||
If an exception is thrown, the constructor has no effect.</p>
|
||||
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
|
||||
<pre>~shared_ptr(); // never throws</pre>
|
||||
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
|
||||
deletes the object pointed to by the stored pointer.
|
||||
Note that <b>delete</b> on a pointer with a value of 0 is harmless.
|
||||
<b>T</b> need not be a complete type.
|
||||
The guarantee that this does not throw exceptions depends on the requirement that the
|
||||
deleted object's destructor does not throw exceptions.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="operator=">assignment</a></h3>
|
||||
|
||||
<pre>shared_ptr & <a href="#assignment">operator=</a>(shared_ptr const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
template<typename Y> shared_ptr & <a href="#assignment">operator=</a>(std::auto_ptr<Y> & r);</pre>
|
||||
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>,
|
||||
which may be thrown during assignment from <b>auto_ptr</b>.
|
||||
If an exception is thrown, the assignment has no effect.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
|
||||
<pre>void reset(T * p = 0);</pre>
|
||||
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, <b>delete p</b> is called.</p>
|
||||
|
||||
<pre>template<typename D> void reset(T * p, D d);</pre>
|
||||
<p>Constructs a new <b>shared_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>shared_ptr</b> with the new one, destroying the replaced object.
|
||||
<b>D</b>'s copy constructor must not throw.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, <b>d(p)</b> is called.</p>
|
||||
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.</p>
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="unique">unique</a></h3>
|
||||
<pre>bool unique() const; // never throws</pre>
|
||||
<p>Returns true if no other <b>shared_ptr</b> is sharing ownership of
|
||||
the stored pointer, false otherwise.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>shared_ptr</b> that do not use an explicit reference
|
||||
count, it might be removed from some future version. Thus it should
|
||||
be used for debugging purposes only, and not production code.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(shared_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
bool <a href="#operator==">operator==</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator!=">operator!=</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>shared_ptr</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>.
|
||||
The implementation uses std::less<T*> to perform the
|
||||
comparison. This ensures that the comparison is handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).</p>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(shared_ptr<U> const & r); // never throws</pre>
|
||||
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>shared_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer.</p>
|
||||
<p>Note that the seemingly equivalent expression</p>
|
||||
<blockquote><code>shared_ptr<T>(static_cast<T*>(r.get()))</code></blockquote>
|
||||
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p>
|
||||
|
||||
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
shared_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(shared_ptr<U> const & r);</pre>
|
||||
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>shared_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer unless the result of the
|
||||
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the
|
||||
construction of the new <b>shared_ptr</b> if the result of the cast is 0. If an exception is thrown, the
|
||||
cast has no effect.</p>
|
||||
<p>Note that the seemingly equivalent expression</p>
|
||||
<blockquote><code>shared_ptr<T>(dynamic_cast<T*>(r.get()))</code></blockquote>
|
||||
<p>will eventually result in undefined behavior, attempting to delete the same object twice.</p>
|
||||
|
||||
<h2><a name="example">Example</a></h2>
|
||||
|
||||
<p>See <a href="shared_ptr_example.cpp">shared_ptr_example.cpp</a> for a complete example program.
|
||||
The program builds a <b>std::vector</b> and <b>std::set</b> of <b>shared_ptr</b> objects.</p>
|
||||
|
||||
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b> objects
|
||||
will have a use count of 1 rather than a use count of 2, since the set is a <b>std::set</b>
|
||||
rather than a <b>std::multiset</b>, and thus does not contain duplicate entries.
|
||||
Furthermore, the use count may be even higher
|
||||
at various times while <b>push_back</b> and <b>insert</b> 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>
|
||||
variety of circumstances. Getting the memory management and exception handling in this
|
||||
example right without a smart pointer 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>
|
||||
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.
|
||||
Note that there is no need for an explicit destructor.
|
||||
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete type.</p>
|
||||
|
||||
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
|
||||
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> have template parameters supplying
|
||||
traits or policies to allow extensive user customization?<br>
|
||||
<b>A.</b> Parameterization discourages users. <b>Shared_ptr</b> is
|
||||
<b>A.</b> Parameterization discourages users. The <b>shared_ptr</b> template is
|
||||
carefully crafted to meet common needs without extensive parameterization.
|
||||
Someday a highly configurable smart pointer may be invented that is also very
|
||||
easy to use and very hard to misuse. Until then, <b>shared_ptr</b> is the
|
||||
smart pointer of choice for a wide range of applications. (Those
|
||||
interested in policy based smart pointers should read <a href="http://cseng.aw.com/book/0,,0201704315,00.html">Modern
|
||||
C++ Design</a> by Andrei Alexandrescu.)</p>
|
||||
Some day a highly configurable smart pointer may be invented that is also very
|
||||
easy to use and very hard to misuse. Until then, <b>shared_ptr</b> is the
|
||||
smart pointer of choice for a wide range of applications. (Those
|
||||
interested in policy based smart pointers should read
|
||||
<a href="http://cseng.aw.com/book/0,,0201704315,00.html">Modern C++ Design</a> by Andrei Alexandrescu.)</p>
|
||||
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> use a linked list implementation?<br>
|
||||
<b>A.</b> A linked list implementation does not offer enough advantages to
|
||||
offset the added cost of an extra pointer. See <a href="smarttests.htm">timings</a>
|
||||
offset the added cost of an extra pointer. See <a href="smarttests.htm">timings</a>
|
||||
page.</p>
|
||||
<p><b>Q.</b> Why don't <b>shared_ptr</b> (and the other Boost smart pointers)
|
||||
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart pointers)
|
||||
supply an automatic conversion to <b>T*</b>?<br>
|
||||
<b>A.</b> Automatic conversion is believed to be too error prone.</p>
|
||||
|
||||
<p><b>Q.</b> Why does <b>shared_ptr</b> supply use_count()?<br>
|
||||
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
|
||||
progenitors had use_count(), and it was useful in tracking down bugs in a
|
||||
complex project that turned out to have cyclic-dependencies.</p>
|
||||
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> specify complexity requirements?<br>
|
||||
<b>A.</b> Because complexity limit implementors and complicate the specification without apparent benefit to
|
||||
<b>shared_ptr</b> users. For example, error-checking implementations might become non-conforming if they
|
||||
<b>A.</b> Because complexity requirements limit implementors and complicate the
|
||||
specification without apparent benefit to <b>shared_ptr</b> users.
|
||||
For example, error-checking implementations might become non-conforming if they
|
||||
had to meet stringent complexity requirements.</p>
|
||||
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?<br>
|
||||
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
|
||||
because the other copy will still destroy the object.</p>
|
||||
<p>Consider:</p>
|
||||
<blockquote>
|
||||
<pre>shared_ptr<int> a(new int);
|
||||
<blockquote><pre>shared_ptr<int> a(new int);
|
||||
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
|
||||
|
||||
int * p = a.release();
|
||||
|
||||
// Who owns p now? b will still call delete on it in its destructor.</pre>
|
||||
</blockquote>
|
||||
<p>[Provided by Peter Dimov]</p>
|
||||
// Who owns p now? b will still call delete on it in its destructor.</pre></blockquote>
|
||||
|
||||
<p><b>Q.</b> Why doesn't <b>shared_ptr</b> provide (your pet feature here)?<br>
|
||||
<b>A.</b> Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent.
|
||||
[Provided by Peter Dimov]</p>
|
||||
<p><br>
|
||||
</p>
|
||||
<b>A.</b> Because (your pet feature here) would mandate a reference counted
|
||||
implementation or a linked list implementation, or some other specific implementation.
|
||||
This is not the intent.</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->11 January, 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan -->
|
||||
</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"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
any purpose.</p>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
// The application will produce a series of
|
||||
// objects of type Foo which later must be
|
||||
|
@ -17,5 +17,3 @@ example & example::operator=( const example & s )
|
||||
|
||||
void example::do_something()
|
||||
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; }
|
||||
|
||||
example::~example() {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Boost shared_ptr_example2 header file -----------------------------------//
|
||||
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
// This example demonstrates the handle/body idiom (also called pimpl and
|
||||
// several other names). It separates the interface (in this header file)
|
||||
@ -16,7 +16,6 @@ class example
|
||||
{
|
||||
public:
|
||||
example();
|
||||
~example();
|
||||
example( const example & );
|
||||
example & operator=( const example & );
|
||||
void do_something();
|
||||
|
196
smart_ptr.htm
196
smart_ptr.htm
@ -1,126 +1,175 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Smart Pointer Classes</title>
|
||||
<title>Smart Pointers</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Smart
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">Smart
|
||||
Pointers</h1>
|
||||
<p>Smart pointers are classes which store pointers to dynamically allocated
|
||||
(heap) objects. They behave much like built-in C++ pointers except that
|
||||
|
||||
<p>Smart pointers are objects which store pointers to dynamically allocated
|
||||
(heap) objects. They behave much like built-in C++ pointers except that
|
||||
they automatically delete the object pointed to at the appropriate
|
||||
time. Smart pointers are particularly useful in the face of exceptions as
|
||||
time. Smart pointers are particularly useful in the face of exceptions as
|
||||
they ensure proper destruction of dynamically allocated objects. They can also
|
||||
be used to keep track of dynamically allocated objects shared by multiple
|
||||
owners.</p>
|
||||
|
||||
<p>Conceptually, smart pointers are seen as owning the object pointed to, and
|
||||
thus responsible for deletion of the object when it is no longer needed.</p>
|
||||
<p>The header <a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>
|
||||
provides four smart pointer template classes:</p>
|
||||
|
||||
<p>The smart pointer library provides five smart pointer class templates:</p>
|
||||
|
||||
<div align="left">
|
||||
<table border="1" cellpadding="4" cellspacing="4">
|
||||
<tr>
|
||||
<td>
|
||||
<p align="left"><a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a></td>
|
||||
<td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td>
|
||||
<td><a href="../boost/scoped_ptr.hpp"><boost/scoped_ptr.hpp></a></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. Noncopyable.</td>
|
||||
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
|
||||
<td><a href="../boost/scoped_array.hpp"><boost/scoped_array.hpp></a></td>
|
||||
<td>Simple sole ownership of arrays. Noncopyable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="shared_ptr.htm"><strong>shared_ptr</strong></a></td>
|
||||
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
|
||||
<td><a href="../boost/shared_ptr.hpp"><boost/shared_ptr.hpp></a></td>
|
||||
<td>Object ownership shared among multiple pointers</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="shared_array.htm"><strong>shared_array</strong></a></td>
|
||||
<td><a href="shared_array.htm"><b>shared_array</b></a></td>
|
||||
<td><a href="../boost/shared_array.hpp"><boost/shared_array.hpp></a></td>
|
||||
<td>Array ownership shared among multiple pointers.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="weak_ptr.htm"><b>weak_ptr</b></a></td>
|
||||
<td><a href="../boost/weak_ptr.hpp"><boost/weak_ptr.hpp></a></td>
|
||||
<td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<p>These classes are designed to complement the C++ Standard Library <tt>auto_ptr</tt>
|
||||
class.</p>
|
||||
|
||||
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
|
||||
|
||||
<p>They are examples of the "resource acquisition is initialization"
|
||||
idiom described in Bjarne Stroustrup's "The C++ Programming Language",
|
||||
3rd edition, Section 14.4, Resource Management.</p>
|
||||
<p>A test program (<a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>) is
|
||||
|
||||
<p>A test program, <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
|
||||
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="compatibility.htm">compatibility</a> with older versions of
|
||||
the Boost smart pointer library describes some of the changes since earlier versions
|
||||
of the smart pointer implementation.</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><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><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>
|
||||
|
||||
<h2><a name="Common requirements">Common Requirements</a></h2>
|
||||
|
||||
<p>These smart pointer class templates have a template parameter, <b>T</b>, which
|
||||
specifies the type of the object pointed to by the smart pointer. The
|
||||
behavior of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
|
||||
for objects of type <b>T</b> throw exceptions.</p>
|
||||
|
||||
<p><b>T</b> may be an incomplete type at the point of smart pointer
|
||||
declaration. Unless otherwise specified, it is required that <b>T</b>
|
||||
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>
|
||||
including deletion of an incomplete type.
|
||||
See the description of the <a href="../utility/utility.htm#checked_delete"><b>checked_delete</b></a>
|
||||
function template.</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.
|
||||
|
||||
<p>The requirements on <b>T</b> 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 <b>T</b> is an
|
||||
incomplete type. This separates interface from implementation and hides
|
||||
implementation from translation units which merely use the interface.
|
||||
Examples described in the documentation for specific smart pointers illustrate
|
||||
use of smart pointers in these idioms.</p>
|
||||
<h2>Exception safety</h2>
|
||||
|
||||
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type
|
||||
at destruction time, but <b>shared_ptr</b> does not.</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
|
||||
exception is thrown. This means that when an exception is thrown by
|
||||
exception is thrown. This means that when an exception is thrown by
|
||||
an object of one of these classes, the entire program state remains the same as
|
||||
it was prior to the function call which resulted in the exception being
|
||||
thrown. This amounts to a guarantee that there are no detectable side
|
||||
effects. Other functions never throw exceptions. The only exception
|
||||
ever thrown by functions which do throw (assuming <tt>T</tt> meets the <a href="#Common requirements">Common
|
||||
requirements</a>) is <tt>std::bad_alloc</tt>, and that is thrown only by
|
||||
functions which are explicitly documented as possibly throwing <tt>std::bad_alloc</tt>.</p>
|
||||
thrown. This amounts to a guarantee that there are no detectable side
|
||||
effects. Other functions never throw exceptions. The only exception
|
||||
ever thrown by functions which do throw (assuming <b>T</b> meets the
|
||||
<a href="#Common requirements">common requirements</a>) is <b>std::bad_alloc</b>,
|
||||
and that is thrown only by functions which are explicitly documented as possibly
|
||||
throwing <b>std::bad_alloc</b>.</p>
|
||||
|
||||
<h2>Exception-specifications</h2>
|
||||
<p>Exception-specifications are not used; see <a href="../../more/lib_guide.htm#Exception-specification">exception-specification
|
||||
|
||||
<p>Exception-specifications are not used; see
|
||||
<a href="../../more/lib_guide.htm#Exception-specification">exception-specification
|
||||
rationale</a>.</p>
|
||||
<p>All four classes contain member functions which can never throw exceptions,
|
||||
|
||||
<p>All the smart pointer templates contain member functions which can never throw exceptions,
|
||||
because they neither throw exceptions themselves nor call other functions which
|
||||
may throw exceptions. These members are indicated by a comment: <kbd>//
|
||||
never throws</kbd>. </p>
|
||||
may throw exceptions. These members are indicated by a comment:
|
||||
<code>// never throws</code>. </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,
|
||||
throwing exceptions by the <a href="#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2>History and Acknowledgements</h2>
|
||||
|
||||
<p>January 2002. Peter Dimov reworked all four classes, adding features, fixing bugs,
|
||||
and splitting them into four separate headers, and added <b>weak_ptr</b>. See the
|
||||
<a href="compatibility.htm">compatibility</a> page for a summary of the changes.</p>
|
||||
|
||||
<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>
|
||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
|
||||
<p>May, 1999. In April and May, 1999, Valentin Bonnard and David Abrahams
|
||||
made a number of suggestions resulting in numerous improvements. See the
|
||||
revision history in <a href="../../boost/smart_ptr.hpp"><tt>smart_ptr.hpp</tt></a>
|
||||
|
||||
<p>September 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
|
||||
|
||||
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams
|
||||
made a number of suggestions resulting in numerous improvements. See the
|
||||
revision history in <a href="../../boost/smart_ptr.hpp"><b>smart_ptr.hpp</b></a>
|
||||
for the specific changes made as a result of their constructive criticism.</p>
|
||||
<p>Oct, 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee
|
||||
classes named <strong>auto_ptr</strong> and <strong>counted_ptr</strong> which
|
||||
were very similar to what we now call <strong>scoped_ptr</strong> and <strong>shared_ptr</strong>.
|
||||
The committee document was 94-168/N0555, Exception Safe Smart Pointers. In
|
||||
|
||||
<p>October 1998. In 1994 Greg Colvin proposed to the C++ Standards Committee
|
||||
classes named <b>auto_ptr</b> and <b>counted_ptr</b> which
|
||||
were very similar to what we now call <b>scoped_ptr</b> and <b>shared_ptr</b>.
|
||||
The committee document was 94-168/N0555, Exception Safe Smart Pointers. In
|
||||
one of the very few cases where the Library Working Group's recommendations were
|
||||
not followed by the full committee, <strong>counted_ptr</strong> was rejected
|
||||
and surprising transfer-of-ownership semantics were added to <strong>auto-ptr</strong>.</p>
|
||||
<p>Beman Dawes proposed reviving the original semantics under the names <strong>safe_ptr</strong>
|
||||
and <strong>counted_ptr</strong> at an October, 1998, meeting of Per Andersson,
|
||||
not followed by the full committee, <b>counted_ptr</b> was rejected
|
||||
and surprising transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
|
||||
|
||||
<p>Beman Dawes proposed reviving the original semantics under the names <b>safe_ptr</b>
|
||||
and <b>counted_ptr</b> at an October, 1998, meeting of Per Andersson,
|
||||
Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar
|
||||
K<EFBFBD>hl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion,
|
||||
K<EFBFBD>hl, Nathan Myers, Chichiang Wan and Judy Ward. During the discussion,
|
||||
the four class names were finalized, it was decided that there was no need to
|
||||
exactly follow the <strong>std::auto_ptr</strong> interface, and various
|
||||
exactly follow the <b>std::auto_ptr</b> interface, and various
|
||||
function signatures and semantics were finalized.</p>
|
||||
<p>Over the next three months, several implementations were considered for <strong>shared_ptr</strong>,
|
||||
|
||||
<p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
|
||||
and discussed on the <a href="http://www.boost.org">boost.org</a> mailing
|
||||
list. The implementation questions revolved around the reference count
|
||||
list. The implementation questions revolved around the reference count
|
||||
which must be kept, either attached to the pointed to object, or detached
|
||||
elsewhere. Each of those variants have themselves two major variants:
|
||||
|
||||
<ul>
|
||||
<li>Direct detached: the shared_ptr contains a pointer to the object, and a
|
||||
pointer to the count.</li>
|
||||
@ -129,22 +178,29 @@ elsewhere. Each of those variants have themselves two major variants:
|
||||
<li>Embedded attached: the count is a member of the object pointed to.</li>
|
||||
<li>Placement attached: the count is attached via operator new manipulations.</li>
|
||||
</ul>
|
||||
<p>Each implementation technique has advantages and disadvantages. We went
|
||||
|
||||
<p>Each implementation technique has advantages and disadvantages. We went
|
||||
so far as to run various timings of the direct and indirect approaches, and
|
||||
found that at least on Intel Pentium chips there was very little measurable
|
||||
difference. Kevlin Henney provided a paper he wrote on "Counted Body
|
||||
Techniques." Dietmar K<>hl suggested an elegant partial template
|
||||
difference. Kevlin Henney provided a paper he wrote on "Counted Body
|
||||
Techniques." Dietmar K<>hl suggested an elegant partial template
|
||||
specialization technique to allow users to choose which implementation they
|
||||
preferred, and that was also experimented with.</p>
|
||||
|
||||
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will
|
||||
discourage users", and in the end we choose to supply only the direct
|
||||
implementation.</p>
|
||||
|
||||
<p>See the Revision History section of the header for further contributors.</p>
|
||||
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan
|
||||
-->24 May 2001<!--webbot bot="Timestamp" endspan i-checksum="15110"
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan
|
||||
-->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="15110"
|
||||
--></p>
|
||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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"
|
||||
without express or implied warranty, and with no claim as to its suitability for
|
||||
|
@ -13,13 +13,23 @@
|
||||
// 20 Jul 99 header name changed to .hpp
|
||||
// 20 Apr 99 additional error tests added.
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
bool boost_error(char const *, char const *, char const *, long)
|
||||
{
|
||||
return true; // fail with assert()
|
||||
}
|
||||
|
||||
class Incomplete;
|
||||
|
||||
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
|
||||
@ -48,7 +58,7 @@ class UDT {
|
||||
explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
|
||||
~UDT() {
|
||||
--UDT_use_count;
|
||||
cout << "UDT with value " << value_ << " being destroyed" << endl;
|
||||
cout << "UDT with value " << value_ << " being destroyed\n";
|
||||
}
|
||||
long value() const { return value_; }
|
||||
void value( long v ) { value_ = v;; }
|
||||
@ -71,7 +81,7 @@ Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
|
||||
shared_ptr<Incomplete>& i2 )
|
||||
{
|
||||
incomplete.swap(i2);
|
||||
cout << incomplete.use_count() << " " << incomplete.unique() << endl;
|
||||
cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n';
|
||||
return incomplete.get();
|
||||
}
|
||||
// main --------------------------------------------------------------------//
|
||||
@ -186,12 +196,10 @@ int test_main( int, char ** ) {
|
||||
BOOST_TEST( *cp4 == 87654 );
|
||||
BOOST_TEST( cp2.get() == 0 );
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
set< shared_ptr<int> > scp;
|
||||
scp.insert(cp4);
|
||||
BOOST_TEST( scp.find(cp4) != scp.end() );
|
||||
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
||||
#endif
|
||||
|
||||
// test shared_array with a built-in type
|
||||
char * cap = new char [ 100 ];
|
||||
@ -232,12 +240,10 @@ int test_main( int, char ** ) {
|
||||
BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( ca3.get() == 0 );
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
set< shared_array<char> > sca;
|
||||
sca.insert(ca4);
|
||||
BOOST_TEST( sca.find(ca4) != sca.end() );
|
||||
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
||||
#endif
|
||||
|
||||
// test shared_array with user defined type
|
||||
shared_array<UDT> udta ( new UDT[3] );
|
||||
@ -280,7 +286,7 @@ int test_main( int, char ** ) {
|
||||
BOOST_TEST( sup.use_count() == 2 );
|
||||
BOOST_TEST( sup2.use_count() == 2 );
|
||||
|
||||
cout << "OK" << endl;
|
||||
cout << "OK\n";
|
||||
|
||||
new char[12345]; // deliberate memory leak to verify leaks detected
|
||||
|
||||
|
@ -1,295 +0,0 @@
|
||||
// smart pointer test program ----------------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 1998, 1999. 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.
|
||||
|
||||
// Revision History
|
||||
// 24 May 01 use Boost test library for error detection, reporting, add tests
|
||||
// for operations on incomplete types (Beman Dawes)
|
||||
// 29 Nov 99 added std::swap and associative container tests (Darin Adler)
|
||||
// 25 Sep 99 added swap tests
|
||||
// 20 Jul 99 header name changed to .hpp
|
||||
// 20 Apr 99 additional error tests added.
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/scoped_array.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
bool boost_error(char const *, char const *, char const *, long)
|
||||
{
|
||||
return true; // fail with assert()
|
||||
}
|
||||
|
||||
class Incomplete;
|
||||
|
||||
Incomplete * get_ptr( boost::shared_ptr<Incomplete>& incomplete )
|
||||
{
|
||||
return incomplete.get();
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
using boost::scoped_ptr;
|
||||
using boost::scoped_array;
|
||||
using boost::shared_ptr;
|
||||
using boost::shared_array;
|
||||
|
||||
template<typename T>
|
||||
void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); }
|
||||
|
||||
namespace {
|
||||
int UDT_use_count; // independent of pointer maintained counts
|
||||
}
|
||||
|
||||
// user defined type -------------------------------------------------------//
|
||||
|
||||
class UDT {
|
||||
long value_;
|
||||
public:
|
||||
explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
|
||||
~UDT() {
|
||||
--UDT_use_count;
|
||||
cout << "UDT with value " << value_ << " being destroyed" << endl;
|
||||
}
|
||||
long value() const { return value_; }
|
||||
void value( long v ) { value_ = v;; }
|
||||
}; // UDT
|
||||
|
||||
// tests on incomplete types -----------------------------------------------//
|
||||
|
||||
// Certain smart pointer operations are specified to work on incomplete types,
|
||||
// and some uses depend upon this feature. These tests verify compilation
|
||||
// only - the functions aren't actually invoked.
|
||||
|
||||
class Incomplete;
|
||||
|
||||
Incomplete * check_incomplete( scoped_ptr<Incomplete>& incomplete )
|
||||
{
|
||||
return incomplete.get();
|
||||
}
|
||||
|
||||
Incomplete * check_incomplete( shared_ptr<Incomplete>& incomplete,
|
||||
shared_ptr<Incomplete>& i2 )
|
||||
{
|
||||
incomplete.swap(i2);
|
||||
cout << incomplete.use_count() << " " << incomplete.unique() << endl;
|
||||
return incomplete.get();
|
||||
}
|
||||
// main --------------------------------------------------------------------//
|
||||
|
||||
// This isn't a very systematic test; it just hits some of the basics.
|
||||
|
||||
int test_main( int, char ** ) {
|
||||
|
||||
BOOST_TEST( UDT_use_count == 0 ); // reality check
|
||||
|
||||
// test scoped_ptr with a built-in type
|
||||
long * lp = new long;
|
||||
scoped_ptr<long> sp ( lp );
|
||||
BOOST_TEST( sp.get() == lp );
|
||||
BOOST_TEST( lp == sp.get() );
|
||||
BOOST_TEST( &*sp == lp );
|
||||
|
||||
*sp = 1234568901L;
|
||||
BOOST_TEST( *sp == 1234568901L );
|
||||
BOOST_TEST( *lp == 1234568901L );
|
||||
ck( static_cast<long*>(sp.get()), 1234568901L );
|
||||
ck( lp, *sp );
|
||||
|
||||
sp.reset();
|
||||
BOOST_TEST( sp.get() == 0 );
|
||||
|
||||
// test scoped_ptr with a user defined type
|
||||
scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
|
||||
BOOST_TEST( udt_sp->value() == 999888777 );
|
||||
udt_sp.reset();
|
||||
udt_sp.reset( new UDT( 111222333 ) );
|
||||
BOOST_TEST( udt_sp->value() == 111222333 );
|
||||
udt_sp.reset( new UDT( 333222111 ) );
|
||||
BOOST_TEST( udt_sp->value() == 333222111 );
|
||||
|
||||
// test scoped_array with a build-in type
|
||||
char * sap = new char [ 100 ];
|
||||
scoped_array<char> sa ( sap );
|
||||
BOOST_TEST( sa.get() == sap );
|
||||
BOOST_TEST( sap == sa.get() );
|
||||
|
||||
strcpy( sa.get(), "Hot Dog with mustard and relish" );
|
||||
BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
|
||||
BOOST_TEST( sa[0] == 'H' );
|
||||
BOOST_TEST( sa[30] == 'h' );
|
||||
|
||||
sa[0] = 'N';
|
||||
sa[4] = 'd';
|
||||
BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
|
||||
|
||||
sa.reset();
|
||||
BOOST_TEST( sa.get() == 0 );
|
||||
|
||||
// test shared_ptr with a built-in type
|
||||
int * ip = new int;
|
||||
shared_ptr<int> cp ( ip );
|
||||
BOOST_TEST( ip == cp.get() );
|
||||
BOOST_TEST( cp.use_count() == 1 );
|
||||
|
||||
*cp = 54321;
|
||||
BOOST_TEST( *cp == 54321 );
|
||||
BOOST_TEST( *ip == 54321 );
|
||||
ck( static_cast<int*>(cp.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp );
|
||||
|
||||
shared_ptr<int> cp2 ( cp );
|
||||
BOOST_TEST( ip == cp2.get() );
|
||||
BOOST_TEST( cp.use_count() == 2 );
|
||||
BOOST_TEST( cp2.use_count() == 2 );
|
||||
|
||||
BOOST_TEST( *cp == 54321 );
|
||||
BOOST_TEST( *cp2 == 54321 );
|
||||
ck( static_cast<int*>(cp2.get()), 54321 );
|
||||
ck( static_cast<int*>(ip), *cp2 );
|
||||
|
||||
shared_ptr<int> cp3 ( cp );
|
||||
BOOST_TEST( cp.use_count() == 3 );
|
||||
BOOST_TEST( cp2.use_count() == 3 );
|
||||
BOOST_TEST( cp3.use_count() == 3 );
|
||||
cp.reset();
|
||||
BOOST_TEST( cp2.use_count() == 2 );
|
||||
BOOST_TEST( cp3.use_count() == 2 );
|
||||
BOOST_TEST( cp.use_count() == 1 );
|
||||
cp.reset( new int );
|
||||
*cp = 98765;
|
||||
BOOST_TEST( *cp == 98765 );
|
||||
*cp3 = 87654;
|
||||
BOOST_TEST( *cp3 == 87654 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
cp.swap( cp3 );
|
||||
BOOST_TEST( *cp == 87654 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
BOOST_TEST( *cp3 == 98765 );
|
||||
cp.swap( cp3 );
|
||||
BOOST_TEST( *cp == 98765 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
BOOST_TEST( *cp3 == 87654 );
|
||||
cp2 = cp2;
|
||||
BOOST_TEST( cp2.use_count() == 2 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
cp = cp2;
|
||||
BOOST_TEST( cp2.use_count() == 3 );
|
||||
BOOST_TEST( *cp2 == 87654 );
|
||||
BOOST_TEST( cp.use_count() == 3 );
|
||||
BOOST_TEST( *cp == 87654 );
|
||||
|
||||
shared_ptr<int> cp4;
|
||||
swap( cp2, cp4 );
|
||||
BOOST_TEST( cp4.use_count() == 3 );
|
||||
BOOST_TEST( *cp4 == 87654 );
|
||||
BOOST_TEST( cp2.get() == 0 );
|
||||
|
||||
set< shared_ptr<int> > scp;
|
||||
scp.insert(cp4);
|
||||
BOOST_TEST( scp.find(cp4) != scp.end() );
|
||||
BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
|
||||
|
||||
// test shared_array with a built-in type
|
||||
char * cap = new char [ 100 ];
|
||||
shared_array<char> ca ( cap );
|
||||
BOOST_TEST( ca.get() == cap );
|
||||
BOOST_TEST( cap == ca.get() );
|
||||
BOOST_TEST( &ca[0] == cap );
|
||||
|
||||
strcpy( ca.get(), "Hot Dog with mustard and relish" );
|
||||
BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
|
||||
|
||||
BOOST_TEST( ca[0] == 'H' );
|
||||
BOOST_TEST( ca[30] == 'h' );
|
||||
|
||||
shared_array<char> ca2 ( ca );
|
||||
shared_array<char> ca3 ( ca2 );
|
||||
|
||||
ca[0] = 'N';
|
||||
ca[4] = 'd';
|
||||
BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( ca.use_count() == 3 );
|
||||
BOOST_TEST( ca2.use_count() == 3 );
|
||||
BOOST_TEST( ca3.use_count() == 3 );
|
||||
ca2.reset();
|
||||
BOOST_TEST( ca.use_count() == 2 );
|
||||
BOOST_TEST( ca3.use_count() == 2 );
|
||||
BOOST_TEST( ca2.use_count() == 1 );
|
||||
|
||||
ca.reset();
|
||||
BOOST_TEST( ca.get() == 0 );
|
||||
|
||||
shared_array<char> ca4;
|
||||
swap( ca3, ca4 );
|
||||
BOOST_TEST( ca4.use_count() == 1 );
|
||||
BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
|
||||
BOOST_TEST( ca3.get() == 0 );
|
||||
|
||||
set< shared_array<char> > sca;
|
||||
sca.insert(ca4);
|
||||
BOOST_TEST( sca.find(ca4) != sca.end() );
|
||||
BOOST_TEST( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
|
||||
|
||||
// test shared_array with user defined type
|
||||
shared_array<UDT> udta ( new UDT[3] );
|
||||
|
||||
udta[0].value( 111 );
|
||||
udta[1].value( 222 );
|
||||
udta[2].value( 333 );
|
||||
shared_array<UDT> udta2 ( udta );
|
||||
|
||||
BOOST_TEST( udta[0].value() == 111 );
|
||||
BOOST_TEST( udta[1].value() == 222 );
|
||||
BOOST_TEST( udta[2].value() == 333 );
|
||||
BOOST_TEST( udta2[0].value() == 111 );
|
||||
BOOST_TEST( udta2[1].value() == 222 );
|
||||
BOOST_TEST( udta2[2].value() == 333 );
|
||||
udta2.reset();
|
||||
BOOST_TEST( udta2.get() == 0 );
|
||||
BOOST_TEST( udta.use_count() == 1 );
|
||||
BOOST_TEST( udta2.use_count() == 1 );
|
||||
|
||||
BOOST_TEST( UDT_use_count == 4 ); // reality check
|
||||
|
||||
// test shared_ptr with a user defined type
|
||||
UDT * up = new UDT;
|
||||
shared_ptr<UDT> sup ( up );
|
||||
BOOST_TEST( up == sup.get() );
|
||||
BOOST_TEST( sup.use_count() == 1 );
|
||||
|
||||
sup->value( 54321 ) ;
|
||||
BOOST_TEST( sup->value() == 54321 );
|
||||
BOOST_TEST( up->value() == 54321 );
|
||||
|
||||
shared_ptr<UDT> sup2;
|
||||
sup2 = sup;
|
||||
BOOST_TEST( sup2->value() == 54321 );
|
||||
BOOST_TEST( sup.use_count() == 2 );
|
||||
BOOST_TEST( sup2.use_count() == 2 );
|
||||
sup2 = sup2;
|
||||
BOOST_TEST( sup2->value() == 54321 );
|
||||
BOOST_TEST( sup.use_count() == 2 );
|
||||
BOOST_TEST( sup2.use_count() == 2 );
|
||||
|
||||
cout << "OK" << endl;
|
||||
|
||||
new char[12345]; // deliberate memory leak to verify leaks detected
|
||||
|
||||
return 0;
|
||||
} // main
|
||||
|
@ -1,13 +1,15 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>boost: smart pointer tests</title>
|
||||
<title>Smart Pointer Timings</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<!--
|
||||
-->
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Smart
|
||||
Pointers Timings </h1>
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" WIDTH="277" HEIGHT="86">Smart Pointer Timings</h1>
|
||||
|
||||
<p>In late January 2000, Mark Borgerding put forward a suggestion to boost for
|
||||
a new design of smart pointer whereby an intrusive doubly linked list is used
|
||||
@ -19,9 +21,10 @@ Pointers Timings </h1>
|
||||
mailing list and the tests which this page describes were performed to provide
|
||||
a guide for current and future investigations into smart pointer implementation
|
||||
strategies.</p>
|
||||
<p>Thanks are due to <a href="../../people/dave_abrahams.htm"> Dave Abrahams</a>,
|
||||
<a href="../../people/gavin_collings.htm"> Gavin Collings</a>, <a href="../../people/greg_colvin.htm"> Greg Colvin</a> and
|
||||
<a href="../../people/beman_dawes.html"> Beman Dawes</a>
|
||||
<p>Thanks are due to <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>,
|
||||
<a href="../../people/gavin_collings.htm">Gavin Collings</a>,
|
||||
<a href="../../people/greg_colvin.htm">Greg Colvin</a> and
|
||||
<a href="../../people/beman_dawes.html">Beman Dawes</a>
|
||||
for test code and trial implementations, the final version of which can be found
|
||||
in .zip format <a href="smarttest.zip">here</a>.</p>
|
||||
<h2>Description</h2>
|
||||
@ -75,7 +78,7 @@ Pointers Timings </h1>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20"> </td>
|
||||
<td><img src="msvcspeed.gif" width="560" height="355"></td>
|
||||
<td><img src="msvcspeed.gif" width="560" height="355" alt="MSVC speed graph"></td>
|
||||
<td width="20"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -85,7 +88,7 @@ Pointers Timings </h1>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><img src="gccspeed.gif" width="560" height="355"></td>
|
||||
<td><img src="gccspeed.gif" width="560" height="355" alt="GCC speed graph"></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -530,7 +533,7 @@ Pointers Timings </h1>
|
||||
spreads its information as in the case of linked pointer.</li>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->19 August 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
|
||||
and distribute this document is granted provided this copyright notice appears in all
|
||||
|
233
weak_ptr.htm
Normal file
233
weak_ptr.htm
Normal file
@ -0,0 +1,233 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<title>weak_ptr</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="middle" width="277" height="86">weak_ptr class template</h1>
|
||||
|
||||
<p><a href="#Introduction">Introduction</a><br>
|
||||
<a href="#Synopsis">Synopsis</a><br>
|
||||
<a href="#Members">Members</a><br>
|
||||
<a href="#functions">Free Functions</a><br>
|
||||
<a href="#example">Example</a><br>
|
||||
<a href="#Handle/Body">Handle/Body Idiom</a><br>
|
||||
<a href="#FAQ">Frequently Asked Questions</a><br>
|
||||
<a href="smarttests.htm">Smart Pointer Timings</a></p>
|
||||
|
||||
<h2><a name="Introduction">Introduction</a></h2>
|
||||
|
||||
<p>The <b>weak_ptr</b> class template stores a pointer to an
|
||||
object that's already managed by a <b>shared_ptr</b>. When the
|
||||
object last <b>shared_ptr</b> to the object goes away and the object
|
||||
is deleted, all <b>weak_ptr</b> objects have their stored pointers
|
||||
set to 0.</p>
|
||||
|
||||
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b>
|
||||
and <b>Assignable</b> requirements of the C++ Standard Library, and so
|
||||
can be used in standard library containers. Comparison operators
|
||||
are supplied so that <b>weak_ptr</b> works with
|
||||
the standard library's associative containers.</p>
|
||||
|
||||
<p>The class template is parameterized on <b>T</b>, the type of the object
|
||||
pointed to. <b>T</b> must meet the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>namespace boost {
|
||||
|
||||
template<typename T> class weak_ptr {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
explicit <a href="#constructors">weak_ptr</a>();
|
||||
template<typename Y> <a href="#constructors">weak_ptr</a>(shared_ptr<Y> const & r); // never throws
|
||||
<a href="#destructor">~weak_ptr</a>(); // never throws
|
||||
|
||||
<a href="#constructors">weak_ptr</a>(weak_ptr const & r); // never throws
|
||||
template<typename Y> <a href="#constructors">weak_ptr</a>(weak_ptr<Y> const & r); // never throws
|
||||
|
||||
weak_ptr & <a href="#assignment">operator=</a>(weak_ptr const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(weak_ptr<Y> const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws
|
||||
|
||||
void <a href="#reset">reset</a>(); // never throws
|
||||
|
||||
T & <a href="#indirection">operator*</a>() const; // never throws
|
||||
T * <a href="#indirection">operator-></a>() const; // never throws
|
||||
T * <a href="#get">get</a>() const; // never throws
|
||||
|
||||
long <a href="#use_count">use_count</a>() const; // never throws
|
||||
|
||||
void <a href="#swap">swap</a>(weak_ptr<T> & b); // never throws
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator==">operator==</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator!=">operator!=</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
|
||||
template<typename T> void <a href="#free-swap">swap</a>(weak_ptr<T> & a, weak_ptr<T> & b); // never throws
|
||||
|
||||
template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr<U> const & r); // never throws
|
||||
template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr<U> const & r);
|
||||
|
||||
}</pre>
|
||||
|
||||
<h2><a name="Members">Members</a></h2>
|
||||
|
||||
<h3><a name="element_type">element_type</a></h3>
|
||||
<pre>typedef T element_type;</pre>
|
||||
<p>Provides the type of the stored pointer.</p>
|
||||
|
||||
<h3><a name="constructors">constructors</a></h3>
|
||||
|
||||
<pre>explicit weak_ptr();</pre>
|
||||
<p>Constructs a <b>weak_ptr</b>, with 0 as its stored pointer.
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, the constructor has no effect.</p>
|
||||
|
||||
<pre>template<typename Y> weak_ptr</a>(shared_ptr<Y> const & r); // never throws</pre>
|
||||
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the pointer stored in <b>r</b>.
|
||||
Afterwards, the <a href="#use_count">use count</a> for all copies is unchanged.
|
||||
When the last <b>shared_ptr</b> is destroyed, the use count and stored pointer become 0.
|
||||
The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
|
||||
If an exception is thrown, the constructor has no effect.</p>
|
||||
|
||||
<pre>weak_ptr(weak_ptr const & r); // never throws
|
||||
template<typename Y> weak_ptr(weak_ptr<Y> const & r); // never throws</pre>
|
||||
<p>Constructs a <b>weak_ptr</b>, as if by storing a copy of the
|
||||
pointer stored in <b>r</b>.</p>
|
||||
|
||||
<h3><a name="destructor">destructor</a></h3>
|
||||
|
||||
<pre>~weak_ptr(); // never throws</pre>
|
||||
<p>Destroys this <b>weak_ptr</b> but has no effect on the object its stored pointer points to.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer <a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="operator=">assignment</a></h3>
|
||||
|
||||
<pre>weak_ptr & <a href="#assignment">operator=</a>(weak_ptr const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(weak_ptr<Y> const & r); // never throws
|
||||
template<typename Y> weak_ptr & <a href="#assignment">operator=</a>(shared_ptr<Y> const & r); // never throws</pre>
|
||||
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.</p>
|
||||
|
||||
<h3><a name="reset">reset</a></h3>
|
||||
|
||||
<pre>void reset();</pre>
|
||||
<p>Constructs a new <b>weak_ptr</b> as described <a href="#constructors">above</a>,
|
||||
then replaces this <b>weak_ptr</b> with the new one, destroying the replaced object.
|
||||
The only exception which may be thrown is <b>std::bad_alloc</b>. If
|
||||
an exception is thrown, the <b>reset</b> has no effect.</p>
|
||||
|
||||
<h3><a name="indirection">indirection</a></h3>
|
||||
|
||||
<pre>T & operator*() const; // never throws</pre>
|
||||
<p>Returns a reference to the object pointed to by the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.
|
||||
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.</p>
|
||||
|
||||
<pre>T * operator->() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
Behavior is undefined if the stored pointer is 0.
|
||||
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.</p>
|
||||
|
||||
<h3><a name="get">get</a></h3>
|
||||
<pre>T * get() const; // never throws</pre>
|
||||
<p>Returns the stored pointer.
|
||||
Note that the stored pointer becomes 0 if all <b>shared_ptr</b> objects for that
|
||||
pointer are destroyed.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h3><a name="use_count">use_count</a></h3>
|
||||
<pre>long use_count() const; // never throws</pre>
|
||||
<p>Returns the number of <b>shared_ptr</b> objects sharing ownership of the
|
||||
stored pointer.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>Because <b>use_count</b> is not necessarily efficient to implement for
|
||||
implementations of <b>weak_ptr</b> that do not use an explicit reference
|
||||
count, it might be removed from some future version. Thus it should
|
||||
be used for debugging purposes only, and <b>get</b> should be used for
|
||||
production code.</p>
|
||||
|
||||
<h3><a name="swap">swap</a></h3>
|
||||
<pre>void swap(weak_ptr & b); // never throws</pre>
|
||||
<p>Exchanges the contents of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
|
||||
<h3><a name="comparison">comparison</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
bool <a href="#operator==">operator==</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator!=">operator!=</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws
|
||||
template<typename T, typename U>
|
||||
bool <a href="#operator<">operator<</a>(weak_ptr<T> const & a, weak_ptr<U> const & b); // never throws</pre>
|
||||
<p>Compares the stored pointers of the two smart pointers.
|
||||
<b>T</b> need not be a complete type.
|
||||
See the smart pointer
|
||||
<a href="smart_ptr.htm#Common requirements">common requirements</a>.</p>
|
||||
<p>The <b>operator<</b> overload is provided to define an ordering so that <b>weak_ptr</b>
|
||||
objects can be used in associative containers such as <b>std::map</b>.
|
||||
The implementation uses std::less<T*> to perform the
|
||||
comparison. This ensures that the comparison is handled correctly, since the
|
||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
|
||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
|
||||
paragraph 8).</p>
|
||||
|
||||
<h3><a name="free-swap">swap</a></h3>
|
||||
<pre>template<typename T>
|
||||
void swap(weak_ptr<T> & a, weak_ptr<T> & b) // never throws</pre>
|
||||
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
|
||||
Provided as an aid to generic programming.</p>
|
||||
|
||||
<h3><a name="shared_static_cast">shared_static_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_static_cast">shared_static_cast</a>(weak_ptr<U> const & r); // never throws</pre>
|
||||
<p>Perform a <b>static_cast</b> on the stored pointer, returning another <b>weak_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer.</p>
|
||||
|
||||
<h3><a name="shared_dynamic_cast">shared_dynamic_cast</a></h3>
|
||||
<pre>template<typename T, typename U>
|
||||
weak_ptr<T> <a href="#shared_dynamic_cast">shared_dynamic_cast</a>(weak_ptr<U> const & r);</pre>
|
||||
<p>Perform a <b>dynamic_cast</b> on the stored pointer, returning another <b>weak_ptr</b>.
|
||||
The resulting smart pointer will share its use count with the original pointer unless the result of the
|
||||
cast is 0. The only exception which may be thrown is <b>std::bad_alloc</b>, which may be thrown during the
|
||||
construction of the new <b>weak_ptr</b> if the result of the cast is 0. If an exception is thrown, the
|
||||
cast has no effect.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->1 February 2002<!--webbot bot="Timestamp" i-checksum="38439" endspan --></p>
|
||||
|
||||
<p>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
|
||||
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" without express or implied warranty,
|
||||
and with no claim as to its suitability for any purpose.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
Reference in New Issue
Block a user