mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-08-02 14:14:27 +02:00
This commit was manufactured by cvs2svn to create branch 'RC_1_27_0'.
[SVN r12739]
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 <a name="threadsafe">thread safe</a> 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>
|
BIN
gccspeed.gif
Normal file
BIN
gccspeed.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
122
include/boost/detail/atomic_count.hpp
Normal file
122
include/boost/detail/atomic_count.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// typedef <implementation-defined> boost::detail::atomic_count;
|
||||
//
|
||||
// atomic_count a(n);
|
||||
//
|
||||
// (n is convertible to long)
|
||||
//
|
||||
// Effects: Constructs an atomic_count with an initial value of n
|
||||
//
|
||||
// a;
|
||||
//
|
||||
// Returns: (long) the current value of a
|
||||
//
|
||||
// ++a;
|
||||
//
|
||||
// Effects: Atomically increments the value of a
|
||||
// Returns: nothing
|
||||
//
|
||||
// --a;
|
||||
//
|
||||
// Effects: Atomically decrements the value of a
|
||||
// Returns: (long) zero if the new value of a is zero,
|
||||
// unspecified non-zero value otherwise (usually the new value)
|
||||
//
|
||||
// Important note: when --a returns zero, it must act as a
|
||||
// read memory barrier (RMB); i.e. the calling thread must
|
||||
// have a synchronized view of the memory
|
||||
//
|
||||
// On Intel IA-32 (x86) memory is always synchronized, so this
|
||||
// is not a problem.
|
||||
//
|
||||
// On many architectures the atomic instructions already act as
|
||||
// a memory barrier.
|
||||
//
|
||||
// This property is necessary for proper reference counting, since
|
||||
// a thread can update the contents of a shared object, then
|
||||
// release its reference, and another thread may immediately
|
||||
// release the last reference causing object destruction.
|
||||
//
|
||||
// The destructor needs to have a synchronized view of the
|
||||
// object to perform proper cleanup.
|
||||
//
|
||||
// Original example by Alexander Terekhov:
|
||||
//
|
||||
// Given:
|
||||
//
|
||||
// - a mutable shared object OBJ;
|
||||
// - two threads THREAD1 and THREAD2 each holding
|
||||
// a private smart_ptr object pointing to that OBJ.
|
||||
//
|
||||
// t1: THREAD1 updates OBJ (thread-safe via some synchronization)
|
||||
// and a few cycles later (after "unlock") destroys smart_ptr;
|
||||
//
|
||||
// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization
|
||||
// with respect to shared mutable object OBJ; OBJ destructors
|
||||
// are called driven by smart_ptr interface...
|
||||
//
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
typedef long atomic_count;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
|
||||
|
||||
#include <boost/detail/atomic_count_win32.hpp>
|
||||
|
||||
#elif defined(linux) || defined(__linux) || defined(__linux__)
|
||||
|
||||
#include <boost/detail/atomic_count_linux.hpp>
|
||||
|
||||
#elif defined(BOOST_HAS_PTHREADS)
|
||||
|
||||
#include <boost/detail/atomic_count_pthreads.hpp>
|
||||
|
||||
#else
|
||||
|
||||
// #warning Unrecognized platform, detail::atomic_count will not be thread safe
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
typedef long atomic_count;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
|
64
include/boost/detail/atomic_count_linux.hpp
Normal file
64
include/boost/detail/atomic_count_linux.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_linux.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
//
|
||||
// On Linux, atomic.h is usually located in /usr/include/asm
|
||||
//
|
||||
|
||||
#include <asm/atomic.h>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count(long v)
|
||||
{
|
||||
atomic_t init = ATOMIC_INIT(v);
|
||||
value_ = init;
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
atomic_inc(&value_);
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return !atomic_dec_and_test(&value_);
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return atomic_read(&value_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
atomic_t value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_LINUX_HPP_INCLUDED
|
99
include/boost/detail/atomic_count_pthreads.hpp
Normal file
99
include/boost/detail/atomic_count_pthreads.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_pthreads.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
//
|
||||
// The generic pthread_mutex-based implementation sometimes leads to
|
||||
// inefficiencies. Example: a class with two atomic_count members
|
||||
// can get away with a single mutex.
|
||||
//
|
||||
// Define a macro so that users can detect the situation and optimize.
|
||||
//
|
||||
|
||||
#define BOOST_ATOMIC_COUNT_USES_PTHREADS
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
private:
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
public:
|
||||
|
||||
scoped_lock(pthread_mutex_t & m): m_(m)
|
||||
{
|
||||
pthread_mutex_lock(&m_);
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
pthread_mutex_unlock(&m_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pthread_mutex_t & m_;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
explicit atomic_count(long v): value_(v)
|
||||
{
|
||||
pthread_mutex_init(&mutex_, 0);
|
||||
}
|
||||
|
||||
~atomic_count()
|
||||
{
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
scoped_lock lock(mutex_);
|
||||
++value_;
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
scoped_lock lock(mutex_);
|
||||
return --value_;
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
scoped_lock lock(mutex_);
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
mutable pthread_mutex_t mutex_;
|
||||
long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
|
68
include/boost/detail/atomic_count_win32.hpp
Normal file
68
include/boost/detail/atomic_count_win32.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/atomic_count_win32.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Avoid #including <windows.h>
|
||||
|
||||
namespace win32
|
||||
{
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement(long volatile *);
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement(long volatile *);
|
||||
}
|
||||
|
||||
class atomic_count
|
||||
{
|
||||
public:
|
||||
|
||||
explicit atomic_count(long v): value_(v)
|
||||
{
|
||||
}
|
||||
|
||||
long operator++()
|
||||
{
|
||||
return win32::InterlockedIncrement(&value_);
|
||||
}
|
||||
|
||||
long operator--()
|
||||
{
|
||||
return win32::InterlockedDecrement(&value_);
|
||||
}
|
||||
|
||||
operator long() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
atomic_count(atomic_count const &);
|
||||
atomic_count & operator=(atomic_count const &);
|
||||
|
||||
volatile long value_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
|
136
include/boost/detail/shared_array_nmt.hpp
Normal file
136
include/boost/detail/shared_array_nmt.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// detail/shared_array_nmt.hpp - shared_array.hpp without member templates
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/shared_array.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
#include <algorithm> // for std::swap
|
||||
#include <functional> // for std::less
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class shared_array
|
||||
{
|
||||
private:
|
||||
|
||||
typedef detail::atomic_count count_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_array(T * p = 0): px(p)
|
||||
{
|
||||
try // prevent leak if new throws
|
||||
{
|
||||
pn = new count_type(1);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
checked_array_delete(p);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
~shared_array()
|
||||
{
|
||||
if(--*pn == 0)
|
||||
{
|
||||
checked_array_delete(px);
|
||||
delete pn;
|
||||
}
|
||||
}
|
||||
|
||||
shared_array(shared_array const & r) : px(r.px) // never throws
|
||||
{
|
||||
pn = r.pn;
|
||||
++*pn;
|
||||
}
|
||||
|
||||
shared_array & operator=(shared_array const & r)
|
||||
{
|
||||
shared_array(r).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(T * p = 0)
|
||||
{
|
||||
BOOST_ASSERT(p == 0 || p != px);
|
||||
shared_array(p).swap(*this);
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
T & operator[](std::ptrdiff_t i) const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
BOOST_ASSERT(i >= 0);
|
||||
return px[i];
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return *pn;
|
||||
}
|
||||
|
||||
bool unique() const // never throws
|
||||
{
|
||||
return *pn == 1;
|
||||
}
|
||||
|
||||
void swap(shared_array<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
std::swap(pn, other.pn);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T * px; // contained pointer
|
||||
count_type * pn; // ptr to reference counter
|
||||
|
||||
}; // shared_array
|
||||
|
||||
template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b)
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b)
|
||||
{
|
||||
return std::less<T*>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<class T> void swap(shared_array<T> & a, shared_array<T> & b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
|
284
include/boost/detail/shared_count.hpp
Normal file
284
include/boost/detail/shared_count.hpp
Normal file
@@ -0,0 +1,284 @@
|
||||
#ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// detail/shared_count.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
# include <memory>
|
||||
#endif
|
||||
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class counted_base
|
||||
{
|
||||
public:
|
||||
|
||||
typedef atomic_count count_type;
|
||||
|
||||
// pre: initial_use_count <= initial_weak_count
|
||||
|
||||
explicit counted_base(long initial_use_count, long initial_weak_count):
|
||||
use_count_(initial_use_count), weak_count_(initial_weak_count), self_deleter_(&self_delete)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~counted_base() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
// dispose() is called when use_count_ drops to zero, to release
|
||||
// the resources managed by *this.
|
||||
//
|
||||
// counted_base doesn't manage any resources except itself, and
|
||||
// the default implementation is a no-op.
|
||||
//
|
||||
// dispose() is not pure virtual since weak_ptr instantiates a
|
||||
// counted_base in its default constructor.
|
||||
|
||||
virtual void dispose() // nothrow
|
||||
{
|
||||
}
|
||||
|
||||
void add_ref() // nothrow
|
||||
{
|
||||
++use_count_;
|
||||
++weak_count_;
|
||||
}
|
||||
|
||||
void release() // nothrow
|
||||
{
|
||||
if(--use_count_ == 0)
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
if(--weak_count_ == 0)
|
||||
{
|
||||
// not a direct 'delete this', because the inlined
|
||||
// release() may use a different heap manager
|
||||
self_deleter_(this);
|
||||
}
|
||||
}
|
||||
|
||||
void weak_add_ref() // nothrow
|
||||
{
|
||||
++weak_count_;
|
||||
}
|
||||
|
||||
void weak_release() // nothrow
|
||||
{
|
||||
if(--weak_count_ == 0)
|
||||
{
|
||||
self_deleter_(this);
|
||||
}
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return use_count_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
counted_base(counted_base const &);
|
||||
counted_base & operator= (counted_base const &);
|
||||
|
||||
static void self_delete(counted_base * p)
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
// inv: use_count_ <= weak_count_
|
||||
|
||||
count_type use_count_;
|
||||
count_type weak_count_;
|
||||
|
||||
void (*self_deleter_) (counted_base *);
|
||||
};
|
||||
|
||||
template<class P, class D> class counted_base_impl: public counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
P ptr; // copy constructor must not throw
|
||||
D del; // copy constructor must not throw
|
||||
|
||||
counted_base_impl(counted_base_impl const &);
|
||||
counted_base_impl & operator= (counted_base_impl const &);
|
||||
|
||||
public:
|
||||
|
||||
// pre: initial_use_count <= initial_weak_count, d(p) must not throw
|
||||
|
||||
counted_base_impl(P p, D d, long initial_use_count, long initial_weak_count):
|
||||
counted_base(initial_use_count, initial_weak_count), ptr(p), del(d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void dispose() // nothrow
|
||||
{
|
||||
del(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class shared_count
|
||||
{
|
||||
private:
|
||||
|
||||
counted_base * pi_;
|
||||
|
||||
friend class weak_count;
|
||||
|
||||
public:
|
||||
|
||||
template<class P, class D> shared_count(P p, D d): pi_(0)
|
||||
{
|
||||
try
|
||||
{
|
||||
pi_ = new counted_base_impl<P, D>(p, d, 1, 1);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
d(p); // delete p
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
// auto_ptr<Y> is special cased to provide the strong guarantee
|
||||
|
||||
template<typename Y>
|
||||
explicit shared_count(std::auto_ptr<Y> & r): pi_(new counted_base_impl< Y *, checked_deleter<Y> >(r.get(), checked_deleter<Y>(), 1, 1))
|
||||
{
|
||||
r.release();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
~shared_count() // nothrow
|
||||
{
|
||||
pi_->release();
|
||||
}
|
||||
|
||||
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
|
||||
{
|
||||
pi_->add_ref();
|
||||
}
|
||||
|
||||
shared_count & operator= (shared_count const & r) // nothrow
|
||||
{
|
||||
counted_base * tmp = r.pi_;
|
||||
tmp->add_ref();
|
||||
pi_->release();
|
||||
pi_ = tmp;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(shared_count & r) // nothrow
|
||||
{
|
||||
counted_base * tmp = r.pi_;
|
||||
r.pi_ = pi_;
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return pi_->use_count();
|
||||
}
|
||||
|
||||
bool unique() const // nothrow
|
||||
{
|
||||
return pi_->use_count() == 1;
|
||||
}
|
||||
};
|
||||
|
||||
class weak_count
|
||||
{
|
||||
private:
|
||||
|
||||
counted_base * pi_;
|
||||
|
||||
public:
|
||||
|
||||
weak_count(): pi_(new counted_base(0, 1)) // can throw
|
||||
{
|
||||
}
|
||||
|
||||
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
|
||||
{
|
||||
pi_->weak_add_ref();
|
||||
}
|
||||
|
||||
weak_count(weak_count const & r): pi_(r.pi_) // nothrow
|
||||
{
|
||||
pi_->weak_add_ref();
|
||||
}
|
||||
|
||||
~weak_count() // nothrow
|
||||
{
|
||||
pi_->weak_release();
|
||||
}
|
||||
|
||||
weak_count & operator= (shared_count const & r) // nothrow
|
||||
{
|
||||
counted_base * tmp = r.pi_;
|
||||
tmp->weak_add_ref();
|
||||
pi_->weak_release();
|
||||
pi_ = tmp;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
weak_count & operator= (weak_count const & r) // nothrow
|
||||
{
|
||||
counted_base * tmp = r.pi_;
|
||||
tmp->weak_add_ref();
|
||||
pi_->weak_release();
|
||||
pi_ = tmp;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(weak_count & r) // nothrow
|
||||
{
|
||||
counted_base * tmp = r.pi_;
|
||||
r.pi_ = pi_;
|
||||
pi_ = tmp;
|
||||
}
|
||||
|
||||
long use_count() const // nothrow
|
||||
{
|
||||
return pi_->use_count();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
|
166
include/boost/detail/shared_ptr_nmt.hpp
Normal file
166
include/boost/detail/shared_ptr_nmt.hpp
Normal file
@@ -0,0 +1,166 @@
|
||||
#ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
|
||||
#define BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/shared_ptr.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/detail/atomic_count.hpp>
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
#include <memory> // for std::auto_ptr
|
||||
#endif
|
||||
|
||||
#include <algorithm> // for std::swap
|
||||
#include <functional> // for std::less
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class shared_ptr
|
||||
{
|
||||
private:
|
||||
|
||||
typedef detail::atomic_count count_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_ptr(T * p = 0): px(p)
|
||||
{
|
||||
try // prevent leak if new throws
|
||||
{
|
||||
pn = new count_type(1);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
checked_delete(p);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
~shared_ptr()
|
||||
{
|
||||
if(--*pn == 0)
|
||||
{
|
||||
checked_delete(px);
|
||||
delete pn;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr(shared_ptr const & r): px(r.px) // never throws
|
||||
{
|
||||
pn = r.pn;
|
||||
++*pn;
|
||||
}
|
||||
|
||||
shared_ptr & operator=(shared_ptr const & r)
|
||||
{
|
||||
shared_ptr(r).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
explicit shared_ptr(std::auto_ptr<T> & r)
|
||||
{
|
||||
pn = new count_type(1); // may throw
|
||||
px = r.release(); // fix: moved here to stop leak if new throws
|
||||
}
|
||||
|
||||
shared_ptr & operator=(std::auto_ptr<T> & r)
|
||||
{
|
||||
shared_ptr(r).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void reset(T * p = 0)
|
||||
{
|
||||
BOOST_ASSERT(p == 0 || p != px);
|
||||
shared_ptr(p).swap(*this);
|
||||
}
|
||||
|
||||
T & operator*() const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
return *px;
|
||||
}
|
||||
|
||||
T * operator->() const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
return px;
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
long use_count() const // never throws
|
||||
{
|
||||
return *pn;
|
||||
}
|
||||
|
||||
bool unique() const // never throws
|
||||
{
|
||||
return *pn == 1;
|
||||
}
|
||||
|
||||
void swap(shared_ptr<T> & other) // never throws
|
||||
{
|
||||
std::swap(px, other.px);
|
||||
std::swap(pn, other.pn);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T * px; // contained pointer
|
||||
count_type * pn; // ptr to reference counter
|
||||
};
|
||||
|
||||
template<class T, class 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)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class 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> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
// get_pointer() enables boost::mem_fn to recognize shared_ptr
|
||||
|
||||
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
|
88
include/boost/scoped_array.hpp
Normal file
88
include/boost/scoped_array.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
||||
#define BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/scoped_array.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp> // in case ptrdiff_t not in std
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// 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(). Use shared_array or std::vector if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_array // noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
T * ptr;
|
||||
|
||||
scoped_array(scoped_array const &);
|
||||
scoped_array & operator=(scoped_array const &);
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_array(T * p = 0) : ptr(p) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
~scoped_array() // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete [] ptr;
|
||||
}
|
||||
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
|
||||
if (ptr != p)
|
||||
{
|
||||
delete [] ptr;
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void swap(scoped_array & b) // never throws
|
||||
{
|
||||
T * tmp = b.ptr;
|
||||
b.ptr = ptr;
|
||||
ptr = tmp;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
|
91
include/boost/scoped_ptr.hpp
Normal file
91
include/boost/scoped_ptr.hpp
Normal file
@@ -0,0 +1,91 @@
|
||||
#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
#define BOOST_SCOPED_PTR_HPP_INCLUDED
|
||||
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/scoped_ptr.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
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;
|
||||
// use shared_ptr or std::auto_ptr if your needs are more complex.
|
||||
|
||||
template<typename T> class scoped_ptr // noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
T* ptr;
|
||||
|
||||
scoped_ptr(scoped_ptr const &);
|
||||
scoped_ptr & operator=(scoped_ptr const &);
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_ptr(T * p = 0): ptr(p) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
~scoped_ptr() // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
void reset(T * p = 0) // never throws
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
|
||||
if (ptr != p)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = p;
|
||||
}
|
||||
}
|
||||
|
||||
T & operator*() const // never throws
|
||||
{
|
||||
BOOST_ASSERT(ptr != 0);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
T * operator->() const // never throws
|
||||
{
|
||||
BOOST_ASSERT(ptr != 0);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void swap(scoped_ptr & b) // never throws
|
||||
{
|
||||
T * tmp = b.ptr;
|
||||
b.ptr = ptr;
|
||||
ptr = tmp;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
142
include/boost/shared_array.hpp
Normal file
142
include/boost/shared_array.hpp
Normal file
@@ -0,0 +1,142 @@
|
||||
#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
|
||||
#define BOOST_SHARED_ARRAY_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// shared_array.hpp
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/shared_array.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
|
||||
#ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
#include <boost/detail/shared_array_nmt.hpp>
|
||||
#else
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
|
||||
#include <boost/detail/shared_count.hpp>
|
||||
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
#include <algorithm> // for std::swap
|
||||
#include <functional> // for std::less
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
//
|
||||
// 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
|
||||
{
|
||||
private:
|
||||
|
||||
// Borland 5.5.1 specific workarounds
|
||||
typedef checked_array_deleter<T> deleter;
|
||||
typedef shared_array<T> this_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_array(T * p = 0): px(p), pn(p, deleter())
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Requirements: D's copy constructor must not throw
|
||||
//
|
||||
// shared_array will release p by calling d(p)
|
||||
//
|
||||
|
||||
template<typename D> shared_array(T * p, D d): px(p), pn(p, d)
|
||||
{
|
||||
}
|
||||
|
||||
// generated copy constructor, assignment, destructor are fine
|
||||
|
||||
void reset(T * p = 0)
|
||||
{
|
||||
BOOST_ASSERT(p == 0 || p != px);
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
template <typename D> void reset(T * p, D d)
|
||||
{
|
||||
this_type(p, d).swap(*this);
|
||||
}
|
||||
|
||||
T & operator[] (std::ptrdiff_t i) const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
BOOST_ASSERT(i >= 0);
|
||||
return px[i];
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
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);
|
||||
pn.swap(other.pn);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
T * px; // contained pointer
|
||||
detail::shared_count pn; // reference counter
|
||||
|
||||
}; // shared_array
|
||||
|
||||
template<typename T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<typename T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
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<typename T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
|
||||
#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
|
252
include/boost/shared_ptr.hpp
Normal file
252
include/boost/shared_ptr.hpp
Normal file
@@ -0,0 +1,252 @@
|
||||
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
|
||||
#define BOOST_SHARED_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// shared_ptr.hpp
|
||||
//
|
||||
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/shared_ptr.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
|
||||
#ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
#include <boost/detail/shared_ptr_nmt.hpp>
|
||||
#else
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
|
||||
#include <boost/detail/shared_count.hpp>
|
||||
|
||||
#include <memory> // for std::auto_ptr
|
||||
#include <algorithm> // for std::swap
|
||||
#include <functional> // for std::less
|
||||
|
||||
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4284) // odd return type for operator->
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct static_cast_tag {};
|
||||
struct dynamic_cast_tag {};
|
||||
|
||||
template<typename T> struct shared_ptr_traits
|
||||
{
|
||||
typedef T & reference;
|
||||
};
|
||||
|
||||
template<> struct shared_ptr_traits<void>
|
||||
{
|
||||
typedef void reference;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
//
|
||||
// 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 weak_ptr;
|
||||
|
||||
template<typename T> class shared_ptr
|
||||
{
|
||||
private:
|
||||
|
||||
// Borland 5.5.1 specific workarounds
|
||||
typedef checked_deleter<T> deleter;
|
||||
typedef shared_ptr<T> this_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit shared_ptr(T * p = 0): px(p), pn(p, deleter())
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// Requirements: D's copy constructor must not throw
|
||||
//
|
||||
// shared_ptr will release p by calling d(p)
|
||||
//
|
||||
|
||||
template<typename D> shared_ptr(T * p, D d): px(p), pn(p, d)
|
||||
{
|
||||
}
|
||||
|
||||
// generated copy constructor, assignment, destructor are fine
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
pn = detail::shared_count(static_cast<element_type *>(0), deleter());
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
template<typename Y>
|
||||
explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn(r)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
|
||||
{
|
||||
px = r.px;
|
||||
pn = r.pn; // shared_count::op= doesn't throw
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_AUTO_PTR
|
||||
|
||||
template<typename Y>
|
||||
shared_ptr & operator=(std::auto_ptr<Y> & r)
|
||||
{
|
||||
this_type(r).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void reset(T * p = 0)
|
||||
{
|
||||
BOOST_ASSERT(p == 0 || p != px);
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
template<typename D> void reset(T * p, D d)
|
||||
{
|
||||
this_type(p, d).swap(*this);
|
||||
}
|
||||
|
||||
typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
return *px;
|
||||
}
|
||||
|
||||
T * operator-> () const // never throws
|
||||
{
|
||||
BOOST_ASSERT(px != 0);
|
||||
return px;
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
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);
|
||||
pn.swap(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)
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
|
||||
private:
|
||||
|
||||
template<typename Y> friend class shared_ptr;
|
||||
template<typename Y> friend class weak_ptr;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
T * px; // contained pointer
|
||||
detail::shared_count pn; // reference counter
|
||||
|
||||
}; // shared_ptr
|
||||
|
||||
template<typename T, typename U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<typename T, typename U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
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<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<typename T> inline T * get_pointer(shared_ptr<T> const & p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
|
||||
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
|
9
include/boost/smart_ptr.hpp
Normal file
9
include/boost/smart_ptr.hpp
Normal file
@@ -0,0 +1,9 @@
|
||||
// Boost smart_ptr.hpp header file -----------------------------------------//
|
||||
|
||||
// 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>
|
186
include/boost/weak_ptr.hpp
Normal file
186
include/boost/weak_ptr.hpp
Normal file
@@ -0,0 +1,186 @@
|
||||
#ifndef BOOST_WEAK_PTR_HPP_INCLUDED
|
||||
#define BOOST_WEAK_PTR_HPP_INCLUDED
|
||||
|
||||
//
|
||||
// weak_ptr.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// 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/libs/smart_ptr/weak_ptr.htm for documentation.
|
||||
//
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <boost/config.hpp> // for broken compiler workarounds
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <boost/detail/shared_count.hpp>
|
||||
|
||||
#include <algorithm> // for std::swap
|
||||
#include <functional> // for std::less
|
||||
|
||||
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4284) // odd return type for operator->
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<typename T> class weak_ptr
|
||||
{
|
||||
private:
|
||||
|
||||
// Borland 5.5.1 specific workarounds
|
||||
typedef weak_ptr<T> this_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
weak_ptr(): px(0), pn()
|
||||
{
|
||||
}
|
||||
|
||||
// generated copy constructor, assignment, destructor are fine
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
|
||||
{
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
weak_ptr(weak_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
|
||||
{
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
pn = detail::weak_count();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Y>
|
||||
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;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
this_type().swap(*this);
|
||||
}
|
||||
|
||||
T * get() const // never throws
|
||||
{
|
||||
return use_count() == 0? 0: px;
|
||||
}
|
||||
|
||||
typename detail::shared_ptr_traits<T>::reference operator* () const // never throws
|
||||
{
|
||||
T * p = get();
|
||||
BOOST_ASSERT(p != 0);
|
||||
return *p;
|
||||
}
|
||||
|
||||
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);
|
||||
pn.swap(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)
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
|
||||
|
||||
private:
|
||||
|
||||
template<typename Y> friend class weak_ptr;
|
||||
|
||||
#endif
|
||||
|
||||
T * px; // contained pointer
|
||||
detail::weak_count pn; // reference counter
|
||||
|
||||
}; // weak_ptr
|
||||
|
||||
template<class T, class U> inline bool operator==(weak_ptr<T> const & a, weak_ptr<U> const & b)
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(weak_ptr<T> const & a, weak_ptr<U> const & b)
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T> inline bool operator<(weak_ptr<T> const & a, weak_ptr<T> const & b)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
// get_pointer() enables boost::mem_fn to recognize weak_ptr
|
||||
|
||||
template<class T> inline T * get_pointer(weak_ptr<T> const & p)
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED
|
47
index.htm
Normal file
47
index.htm
Normal file
@@ -0,0 +1,47 @@
|
||||
<!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>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
||||
<tr>
|
||||
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
|
||||
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home</big></font></a></td>
|
||||
<td><a href="../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries</big></font></a></td>
|
||||
<td><a href="../../people/people.htm"><font face="Arial" color="#FFFFFF"><big>People</big></font></a></td>
|
||||
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ</big></font></a></td>
|
||||
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More</big></font></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<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/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>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 -->1 February 2002<!--webbot bot="Timestamp" endspan i-checksum="14885" -->.</p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
msvcspeed.gif
Normal file
BIN
msvcspeed.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
145
scoped_array.htm
Normal file
145
scoped_array.htm
Normal file
@@ -0,0 +1,145 @@
|
||||
<!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>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<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.
|
||||
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 <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"><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 <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>
|
||||
|
||||
<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>Synopsis</h2>
|
||||
|
||||
<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
|
||||
|
||||
}</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="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++ <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><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-->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>
|
||||
|
||||
</html>
|
217
scoped_ptr.htm
Normal file
217
scoped_ptr.htm
Normal file
@@ -0,0 +1,217 @@
|
||||
<!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>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<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.
|
||||
Because it is <a href="../utility/utility.htm#class noncopyable">noncopyable</a>, it is
|
||||
safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which should not be
|
||||
copied.</p>
|
||||
|
||||
<p>Because <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.</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 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>Synopsis</h2>
|
||||
|
||||
<pre>namespace boost {
|
||||
|
||||
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
|
||||
|
||||
}</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="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++ <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>
|
||||
|
||||
<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()
|
||||
{
|
||||
boost::scoped_ptr<Shoe> x(new Shoe);
|
||||
MyClass my_instance;
|
||||
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 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 file.</p>
|
||||
|
||||
<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 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 -->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>
|
||||
|
||||
</html>
|
16
scoped_ptr_example.cpp
Normal file
16
scoped_ptr_example.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
// Boost scoped_ptr_example implementation file -----------------------------//
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
|
||||
void example::do_something() { std::cout << "did something\n"; }
|
||||
|
||||
example::~example() {}
|
22
scoped_ptr_example.hpp
Normal file
22
scoped_ptr_example.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
// Boost scoped_ptr_example header file ------------------------------------//
|
||||
|
||||
#include <boost/utility.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
|
||||
// this header, scoped_ptr< implementation > is still valid because the type
|
||||
// is complete where it counts - in the inplementation translation unit where
|
||||
// destruction is actually instantiated.
|
||||
|
||||
class example : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
example();
|
||||
~example();
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::scoped_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
10
scoped_ptr_example_test.cpp
Normal file
10
scoped_ptr_example_test.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// Boost scoped_ptr_example_test main program -------------------------------//
|
||||
|
||||
#include "scoped_ptr_example.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example my_example;
|
||||
my_example.do_something();
|
||||
return 0;
|
||||
}
|
224
shared_array.htm
Normal file
224
shared_array.htm
Normal file
@@ -0,0 +1,224 @@
|
||||
<!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>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<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>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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>Synopsis</h2>
|
||||
|
||||
<pre>namespace boost {
|
||||
|
||||
template<typename T> class shared_array {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
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
|
||||
|
||||
<a href="#constructors">shared_array</a>(shared_array const & r); // never throws
|
||||
|
||||
shared_array & <a href="#assignment">operator=</a>(shared_array const & r); // never throws
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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="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 and destructor 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><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 <b>std::less<T *></b> 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 <b>std::less<></b> 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 -->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>
|
356
shared_ptr.htm
Normal file
356
shared_ptr.htm
Normal file
@@ -0,0 +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>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<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="#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>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>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>
|
||||
|
||||
<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>
|
||||
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
|
||||
<pre>namespace boost {
|
||||
|
||||
template<typename T> class shared_ptr {
|
||||
|
||||
public:
|
||||
typedef T <a href="#element_type">element_type</a>;
|
||||
|
||||
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
|
||||
|
||||
<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);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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_ptr<T> & 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, 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="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 and destructor 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 <b>std::less<T *></b> 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 <b>std::less<></b> 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. 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.
|
||||
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. The <b>shared_ptr</b> template is
|
||||
carefully crafted to meet common needs without extensive parameterization.
|
||||
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>
|
||||
page.</p>
|
||||
|
||||
<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 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);
|
||||
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><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
|
||||
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 -->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>
|
96
shared_ptr_example.cpp
Normal file
96
shared_ptr_example.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Boost shared_ptr_example.cpp --------------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes 2001. Permission to copy,
|
||||
// use, modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided "as is"
|
||||
// without express or implied warranty, and with no claim as to its
|
||||
// suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 21 May 01 Initial complete version (Beman Dawes)
|
||||
|
||||
// The original code for this example appeared in the shared_ptr documentation.
|
||||
// Ray Gallimore pointed out that foo_set was missing a Compare template
|
||||
// argument, so would not work as intended. At that point the code was
|
||||
// turned into an actual .cpp file so it could be compiled and tested.
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
// The application will produce a series of
|
||||
// objects of type Foo which later must be
|
||||
// accessed both by occurrence (std::vector)
|
||||
// and by ordering relationship (std::set).
|
||||
|
||||
struct Foo
|
||||
{
|
||||
Foo( int _x ) : x(_x) {}
|
||||
~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
|
||||
int x;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<Foo> FooPtr;
|
||||
|
||||
struct FooPtrOps
|
||||
{
|
||||
bool operator()( const FooPtr & a, const FooPtr & b )
|
||||
{ return a->x > b->x; }
|
||||
void operator()( const FooPtr & a )
|
||||
{ std::cout << a->x << "\n"; }
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<FooPtr> foo_vector;
|
||||
std::set<FooPtr,FooPtrOps> foo_set; // NOT multiset!
|
||||
|
||||
FooPtr foo_ptr( new Foo( 2 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset( new Foo( 1 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset( new Foo( 3 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
foo_ptr.reset ( new Foo( 2 ) );
|
||||
foo_vector.push_back( foo_ptr );
|
||||
foo_set.insert( foo_ptr );
|
||||
|
||||
std::cout << "foo_vector:\n";
|
||||
std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
|
||||
|
||||
std::cout << "\nfoo_set:\n";
|
||||
std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
|
||||
std::cout << "\n";
|
||||
|
||||
// Expected output:
|
||||
//
|
||||
// foo_vector:
|
||||
// 2
|
||||
// 1
|
||||
// 3
|
||||
// 2
|
||||
//
|
||||
// foo_set:
|
||||
// 3
|
||||
// 2
|
||||
// 1
|
||||
//
|
||||
// Destructing a Foo with x=2
|
||||
// Destructing a Foo with x=1
|
||||
// Destructing a Foo with x=3
|
||||
// Destructing a Foo with x=2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
19
shared_ptr_example2.cpp
Normal file
19
shared_ptr_example2.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// Boost shared_ptr_example2 implementation file -----------------------------//
|
||||
|
||||
#include "shared_ptr_example2.hpp"
|
||||
#include <iostream>
|
||||
|
||||
class example::implementation
|
||||
{
|
||||
public:
|
||||
~implementation() { std::cout << "destroying implementation\n"; }
|
||||
};
|
||||
|
||||
example::example() : _imp( new implementation ) {}
|
||||
example::example( const example & s ) : _imp( s._imp ) {}
|
||||
|
||||
example & example::operator=( const example & s )
|
||||
{ _imp = s._imp; return *this; }
|
||||
|
||||
void example::do_something()
|
||||
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; }
|
26
shared_ptr_example2.hpp
Normal file
26
shared_ptr_example2.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Boost shared_ptr_example2 header file -----------------------------------//
|
||||
|
||||
#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)
|
||||
// from the implementation (in shared_ptr_example2.cpp).
|
||||
|
||||
// Note that even though example::implementation is an incomplete type in
|
||||
// some translation units using this header, shared_ptr< implementation >
|
||||
// is still valid because the type is complete where it counts - in the
|
||||
// shared_ptr_example2.cpp translation unit where functions requiring a
|
||||
// complete type are actually instantiated.
|
||||
|
||||
class example
|
||||
{
|
||||
public:
|
||||
example();
|
||||
example( const example & );
|
||||
example & operator=( const example & );
|
||||
void do_something();
|
||||
private:
|
||||
class implementation;
|
||||
boost::shared_ptr< implementation > _imp; // hide implementation details
|
||||
};
|
||||
|
15
shared_ptr_example2_test.cpp
Normal file
15
shared_ptr_example2_test.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
// Boost shared_ptr_example2_test main program ------------------------------//
|
||||
|
||||
#include "shared_ptr_example2.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
example a;
|
||||
a.do_something();
|
||||
example b(a);
|
||||
b.do_something();
|
||||
example c;
|
||||
c = a;
|
||||
c.do_something();
|
||||
return 0;
|
||||
}
|
162
shared_ptr_test.cpp
Normal file
162
shared_ptr_test.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// shared_ptr_test.cpp - a test for shared_ptr.hpp and weak_ptr.hpp
|
||||
//
|
||||
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/weak_ptr.hpp>
|
||||
|
||||
bool boost_error(char const *, char const *, char const *, long)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
int cnt = 0;
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
X()
|
||||
{
|
||||
++cnt;
|
||||
std::cout << "X(" << this << ")::X()\n";
|
||||
}
|
||||
|
||||
virtual ~X()
|
||||
{
|
||||
--cnt;
|
||||
std::cout << "X(" << this << ")::~X()\n";
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
X(X const &);
|
||||
X & operator= (X const &);
|
||||
};
|
||||
|
||||
struct Y: public X
|
||||
{
|
||||
Y()
|
||||
{
|
||||
++cnt;
|
||||
std::cout << "Y(" << this << ")::Y()\n";
|
||||
}
|
||||
|
||||
~Y()
|
||||
{
|
||||
--cnt;
|
||||
std::cout << "Y(" << this << ")::~Y()\n";
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Y(Y const &);
|
||||
Y & operator= (Y const &);
|
||||
};
|
||||
|
||||
int * get_object()
|
||||
{
|
||||
++cnt;
|
||||
std::cout << "get_object()\n";
|
||||
return &cnt;
|
||||
}
|
||||
|
||||
void release_object(int * p)
|
||||
{
|
||||
BOOST_TEST(p == &cnt);
|
||||
--cnt;
|
||||
std::cout << "release_object()\n";
|
||||
}
|
||||
|
||||
int test_main(int, char * [])
|
||||
{
|
||||
using namespace boost;
|
||||
|
||||
{
|
||||
shared_ptr<X> p(new Y);
|
||||
shared_ptr<X> p2(new X);
|
||||
|
||||
shared_ptr<Y> p3 = shared_dynamic_cast<Y>(p);
|
||||
shared_ptr<Y> p4 = shared_dynamic_cast<Y>(p2);
|
||||
|
||||
BOOST_TEST(p.use_count() == 2);
|
||||
BOOST_TEST(p2.use_count() == 1);
|
||||
BOOST_TEST(p3.use_count() == 2);
|
||||
BOOST_TEST(p4.use_count() == 1);
|
||||
|
||||
shared_ptr<void> p5(p);
|
||||
|
||||
std::cout << "--\n";
|
||||
|
||||
p.reset();
|
||||
p2.reset();
|
||||
p3.reset();
|
||||
p4.reset();
|
||||
|
||||
std::cout << "--\n";
|
||||
|
||||
BOOST_TEST(p5.use_count() == 1);
|
||||
|
||||
weak_ptr<X> wp1;
|
||||
|
||||
BOOST_TEST(wp1.use_count() == 0);
|
||||
BOOST_TEST(wp1.get() == 0);
|
||||
|
||||
weak_ptr<X> wp2 = shared_static_cast<X>(p5);
|
||||
|
||||
BOOST_TEST(wp2.use_count() == 1);
|
||||
BOOST_TEST(wp2.get() != 0);
|
||||
|
||||
weak_ptr<Y> wp3 = shared_dynamic_cast<Y>(wp2);
|
||||
|
||||
BOOST_TEST(wp3.use_count() == 1);
|
||||
BOOST_TEST(wp3.get() != 0);
|
||||
BOOST_TEST(wp2 == wp3);
|
||||
|
||||
weak_ptr<X> wp4(wp3);
|
||||
|
||||
wp1 = p2;
|
||||
wp1 = p4;
|
||||
wp1 = wp3;
|
||||
wp1 = wp2;
|
||||
|
||||
BOOST_TEST(wp1.use_count() == 1);
|
||||
BOOST_TEST(wp1.get() != 0);
|
||||
BOOST_TEST(wp1 == wp2);
|
||||
|
||||
p5.reset();
|
||||
|
||||
BOOST_TEST(wp1.use_count() == 0);
|
||||
BOOST_TEST(wp1.get() == 0);
|
||||
|
||||
BOOST_TEST(wp2.use_count() == 0);
|
||||
BOOST_TEST(wp2.get() == 0);
|
||||
|
||||
BOOST_TEST(wp3.use_count() == 0);
|
||||
BOOST_TEST(wp3.get() == 0);
|
||||
|
||||
shared_ptr<int> p6(get_object(), release_object);
|
||||
}
|
||||
|
||||
BOOST_TEST(cnt == 0);
|
||||
|
||||
return 0;
|
||||
}
|
211
smart_ptr.htm
Normal file
211
smart_ptr.htm
Normal file
@@ -0,0 +1,211 @@
|
||||
<!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 Pointers</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
|
||||
Pointers</h1>
|
||||
|
||||
<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
|
||||
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 smart pointer library provides five smart pointer class templates:</p>
|
||||
|
||||
<div align="left">
|
||||
<table border="1" cellpadding="4" cellspacing="4">
|
||||
<tr>
|
||||
<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"><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"><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"><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 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
|
||||
provided to verify correct operation.</p>
|
||||
|
||||
<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 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 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 <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>
|
||||
|
||||
<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
|
||||
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 <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
|
||||
rationale</a>.</p>
|
||||
|
||||
<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:
|
||||
<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>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
|
||||
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"><b>smart_ptr.hpp</b></a>
|
||||
for the specific changes made as a result of their constructive criticism.</p>
|
||||
|
||||
<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, <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,
|
||||
the four class names were finalized, it was decided that there was no need to
|
||||
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 <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
|
||||
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>
|
||||
<li>Indirect detached: the shared_ptr contains a pointer to a helper object,
|
||||
which in turn contains a pointer to the object and the count.</li>
|
||||
<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
|
||||
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
|
||||
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
|
||||
-->4 February 2002<!--webbot bot="Timestamp" endspan i-checksum="40737"
|
||||
--></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>
|
295
smart_ptr_test.cpp
Normal file
295
smart_ptr_test.cpp
Normal file
@@ -0,0 +1,295 @@
|
||||
// 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\n";
|
||||
}
|
||||
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() << '\n';
|
||||
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\n";
|
||||
|
||||
new char[12345]; // deliberate memory leak to verify leaks detected
|
||||
|
||||
return 0;
|
||||
} // main
|
||||
|
BIN
smarttest.zip
Normal file
BIN
smarttest.zip
Normal file
Binary file not shown.
543
smarttests.htm
Normal file
543
smarttests.htm
Normal file
@@ -0,0 +1,543 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<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="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
|
||||
to join together all instances of smart pointers sharing a given raw pointer.
|
||||
This allowed avoidance of the costly heap allocation of a reference count that
|
||||
occurred in the initial construction of the then current version of boost::shared_ptr.
|
||||
Of course, nothing is for free and the benefit here was gained at the expense
|
||||
of increased size and more costly copy operations. A debate ensued on the boost
|
||||
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>
|
||||
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>
|
||||
<p>Two tests were run: the first aimed to obtain timings for two basic individual
|
||||
operations:</p>
|
||||
<ol type="i">
|
||||
<li> Initial construction from raw pointer.</li>
|
||||
<li> An amortized copy operation consisting of half an assignment and half a
|
||||
copy construction - designed to reflect average usage.</li>
|
||||
</ol>
|
||||
<p>The second attempted to gain more insight into normal usage by timing the fill
|
||||
and sort algorithms for vectors and lists filled with the various smart pointers.</p>
|
||||
<p>Five smart pointer implementation strategies were tested:</p>
|
||||
<ol type="i">
|
||||
<li>Counted pointer using a heap allocated reference count, this is referred
|
||||
to as <b>simple counted</b>.</li>
|
||||
<li>Counted pointer using a special purpose allocator for the reference count
|
||||
- <b>special counted</b>.</li>
|
||||
<li>Counted pointer using an intrusive reference count - <b>intrusive</b>.</li>
|
||||
<li>Linked pointer as described above - <b>linked</b>.</li>
|
||||
<li>Cyclic pointer, a counted implementation using a std::deque for allocation
|
||||
with provision for weak pointers and garbage collection of cycles of pointers
|
||||
- <b>cyclic</b>.</li>
|
||||
</ol>
|
||||
<p>on two compilers:</p>
|
||||
<ol type="i">
|
||||
<li>MSVC 6.0 service pack 3, using default release optimization mode (/O2 -
|
||||
optimized for speed, no inlining of functions defined outside a class body
|
||||
unless specified as inline).</li>
|
||||
<li>gcc 2.95.2 using full optimization (-O3 -DNDEBUG).</li>
|
||||
</ol>
|
||||
<p>Additionally, generated pointer sizes (taking into account struct alignment)
|
||||
were compared, as were generated code sizes for MSVC mainly by manual inspection
|
||||
of generated assembly code - a necessity due to function inlining.</p>
|
||||
<p>All tests were run on a PII-200 running Windows NT version 4.0</p>
|
||||
<h2> </h2>
|
||||
<h2>Operation Timing Test Results</h2>
|
||||
<p>The following graphs show the overall time in nanoseconds to acquire a pointer
|
||||
(default construction) perform n amortized copy operations on it and finally
|
||||
release it. The initial allocation time for the contained pointer is not included,
|
||||
although the time for it's deallocation is. The contained pointer pointed to
|
||||
a trivial class, but for the inclusion of an intrusive reference count for the
|
||||
benefit of the intrusive counted shared pointer. A dumb pointer (i.e. a smart
|
||||
pointer that simply acquires and releases its contained pointer with no extra
|
||||
overhead) and a raw pointer were also included for comparison.</p>
|
||||
<table border="0" align="center">
|
||||
<tr>
|
||||
<td width="20" height="20"> </td>
|
||||
<td> </td>
|
||||
<td width="20"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20"> </td>
|
||||
<td><img src="msvcspeed.gif" width="560" height="355" alt="MSVC speed graph"></td>
|
||||
<td width="20"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="20"> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><img src="gccspeed.gif" width="560" height="355" alt="GCC speed graph"></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td height="20"> </td>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<p>Fitting straight lines to the above plots gives the following figures for initialization
|
||||
and amortized copy operation for the two compilers (times in nanoseconds, errors
|
||||
at two standard deviations) : -</p>
|
||||
<p> </p>
|
||||
<h4 align="center">MSVC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="400">
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">
|
||||
<div align="center">initialization</div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">copy operation</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">3000 +/- 170</td>
|
||||
<td class="codetablecell" align="center">104 +/- 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1330 +/- 50</td>
|
||||
<td class="codetablecell" align="center">85 +/- 9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1000 +/- 20</td>
|
||||
<td class="codetablecell" align="center">71 +/- 3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">970 +/- 60</td>
|
||||
<td class="codetablecell" align="center">136 +/- 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">1290 +/- 70</td>
|
||||
<td class="codetablecell" align="center">112 +/- 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">dumb</th>
|
||||
<td class="codetablecell" align="center">1020 +/- 20</td>
|
||||
<td class="codetablecell" align="center">10 +/- 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1038 +/- 30</td>
|
||||
<td class="codetablecell" align="center">10 +/- 5</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h4 align="center"> </h4>
|
||||
<h4 align="center">GCC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="400">
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">
|
||||
<div align="center">initialization</div>
|
||||
</th>
|
||||
<th class="codetabletop" width="120">copy operation</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">4620 +/- 150</td>
|
||||
<td class="codetablecell" align="center">301 +/- 28</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1990 +/- 40</td>
|
||||
<td class="codetablecell" align="center">264 +/- 7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1590 +/- 70</td>
|
||||
<td class="codetablecell" align="center">181 +/- 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">1470 +/- 140</td>
|
||||
<td class="codetablecell" align="center">345 +/- 26</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">2180 +/- 100</td>
|
||||
<td class="codetablecell" align="center">330 +/- 18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">dumb</th>
|
||||
<td class="codetablecell" align="center">1590 +/- 70</td>
|
||||
<td class="codetablecell" align="center">74 +/- 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1430 +/- 60</td>
|
||||
<td class="codetablecell" align="center">27 +/- 11</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Note that the above times include a certain amount of loop overhead etc. for
|
||||
each operation. An estimate of the pure smart pointer operation time 'overhead'
|
||||
can be obtained by subtracting the dumb or raw figure from the smart pointer
|
||||
time of interest.</p>
|
||||
<h3>Detail</h3>
|
||||
<p>The test involved iterating a loop which creates raw pointers. These were then
|
||||
shared among a varying number (set size) of smart pointers. A range of set sizes
|
||||
was used and then a line fitted to get a linear relation with number of initializations
|
||||
and copy-operations. A spreadsheet was used for the line fit, and to produce
|
||||
the performance graphs above.</p>
|
||||
<h2> </h2>
|
||||
<h2>Container Test Results</h2>
|
||||
<p>To gain some insight in to operation within real life programs, this test was
|
||||
devised. Smart pointers were used to fill standard containers which were then
|
||||
sorted.</p>
|
||||
<p>In this case, the contained pointer pointed to a class which initializes a
|
||||
private data member to a random value in its default constructor. This value
|
||||
is used subsequently for the sort comparison test. The class also contains an
|
||||
intrusive reference count for the benefit of the intrusive counted pointer.</p>
|
||||
<p> All times are in seconds for 300,000 contained pointers.</p>
|
||||
<h4 align="center">GCC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="500">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th class="codetabletop" colspan="2">vector</th>
|
||||
<th class="codetabletop" colspan="2">list</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">
|
||||
<div align="center">fill</div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
<th class="codetabletop2" width="80">fill</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">46.54</td>
|
||||
<td class="codetablecell" align="center">2.44</td>
|
||||
<td class="codetablecell" align="center">47.09</td>
|
||||
<td class="codetablecell" align="center">3.22</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">14.02</td>
|
||||
<td class="codetablecell" align="center">2.83</td>
|
||||
<td class="codetablecell" align="center">7.28</td>
|
||||
<td class="codetablecell" align="center">3.21</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">12.15</td>
|
||||
<td class="codetablecell" align="center">1.91</td>
|
||||
<td class="codetablecell" align="center">7.99</td>
|
||||
<td class="codetablecell" align="center">3.08</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">12.46</td>
|
||||
<td class="codetablecell" align="center">2.32</td>
|
||||
<td class="codetablecell" align="center">8.14</td>
|
||||
<td class="codetablecell" align="center">3.27</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">22.60</td>
|
||||
<td class="codetablecell" align="center">3.19</td>
|
||||
<td class="codetablecell" align="center">1.63</td>
|
||||
<td class="codetablecell" align="center">3.18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">11.81</td>
|
||||
<td class="codetablecell" align="center">0.24</td>
|
||||
<td class="codetablecell" align="center">27.51</td>
|
||||
<td class="codetablecell" align="center">0.77</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<h4 align="center">MSVC</h4>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="500">
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th class="codetabletop" colspan="2">vector</th>
|
||||
<th class="codetabletop" colspan="2">list</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th width="120">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">
|
||||
<div align="center">fill</div>
|
||||
</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
<th class="codetabletop2" width="80">fill</th>
|
||||
<th class="codetabletop2" width="80">sort</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1.83</td>
|
||||
<td class="codetablecell" align="center">2.37</td>
|
||||
<td class="codetablecell" align="center">1.86</td>
|
||||
<td class="codetablecell" align="center">4.85</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1.04</td>
|
||||
<td class="codetablecell" align="center">2.35</td>
|
||||
<td class="codetablecell" align="center">1.38</td>
|
||||
<td class="codetablecell" align="center">4.58</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">1.04</td>
|
||||
<td class="codetablecell" align="center">1.84</td>
|
||||
<td class="codetablecell" align="center">1.16</td>
|
||||
<td class="codetablecell" align="center">4.29</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">linked</th>
|
||||
<td class="codetablecell" align="center">1.08</td>
|
||||
<td class="codetablecell" align="center">2.00</td>
|
||||
<td class="codetablecell" align="center">1.21</td>
|
||||
<td class="codetablecell" align="center">4.33</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">cyclic</th>
|
||||
<td class="codetablecell" align="center">1.38</td>
|
||||
<td class="codetablecell" align="center">2.84</td>
|
||||
<td class="codetablecell" align="center">1.47</td>
|
||||
<td class="codetablecell" align="center">4.73</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft" align="right">
|
||||
<div align="right">raw</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">0.67</td>
|
||||
<td class="codetablecell" align="center">0.28</td>
|
||||
<td class="codetablecell" align="center">1.24</td>
|
||||
<td class="codetablecell" align="center">1.81</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p> </p>
|
||||
<h2>Code Size</h2>
|
||||
<p>The following code sizes were determined by inspection of generated code for
|
||||
MSVC only. Sizes are given in the form N / M / I where:</p>
|
||||
<ul type="circle">
|
||||
<li> N is the instruction count of the operation</li>
|
||||
<li>M is the size of the code in bytes</li>
|
||||
<li>I determines whether generated code was inlined or not I = inline, O = "outline"</li>
|
||||
</ul>
|
||||
<p> </p>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="570">
|
||||
<tr>
|
||||
<th height="28" width="140">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="80">
|
||||
<div align="center">ptr()</div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="80">ptr(p)</th>
|
||||
<th height="28" class="codetabletop" width="80">ptr(ptr)</th>
|
||||
<th height="28" class="codetabletop" width="80">op=()</th>
|
||||
<th height="28" class="codetabletop" width="80">
|
||||
<div align="center">~ptr()</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center">38/110/O</td>
|
||||
<td class="codetablecell" align="center">38/110/O</td>
|
||||
<td class="codetablecell" align="center">9/23/I</td>
|
||||
<td class="codetablecell" align="center">22/57/I</td>
|
||||
<td class="codetablecell" align="center">17/40/I</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center"><font size="-1">50/141/O</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">50/141/O</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">9/23/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">23/64/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">13/38/I</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center"><font size="-1">1/2/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">3/6/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">3/6/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">6/11/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">6/11/I</font></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">linked</div>
|
||||
</th>
|
||||
<td class="codetablecell" align="center"><font size="-1">5/19/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">5/15/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">10/30/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">27/59/I</font></td>
|
||||
<td class="codetablecell" align="center"><font size="-1">14/38/I</font></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>During the code inspection, a couple of minor points were noticed: -</p>
|
||||
<ul>
|
||||
<li>Function inlining was critical to performance.</li>
|
||||
<li>For MSVC, at least, a "delete 0" caused execution of 11 assembly
|
||||
instructions, including a function call. So in cases where performance is
|
||||
at an absolute premium it can be worth inserting the extra manual test.</li>
|
||||
</ul>
|
||||
<h2> </h2>
|
||||
<h2>Data Size</h2>
|
||||
<p>The following smart pointer sizes were obtained in bytes</p>
|
||||
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="270">
|
||||
<tr>
|
||||
<th height="28" width="150">
|
||||
<div align="right"></div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="60">
|
||||
<div align="center">MSVC</div>
|
||||
</th>
|
||||
<th height="28" class="codetabletop" width="60">
|
||||
<div align="center">GCC</div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">simple counted</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">special counted</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">12</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">intrusive</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">4</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">4</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">linked</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">12</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">12</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="codetableleft">
|
||||
<div align="right">cyclic</div>
|
||||
</th>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
<td class="codetablecell">
|
||||
<div align="center">8</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2> </h2>
|
||||
<h2>Summary</h2>
|
||||
<p>The timing results mainly speak for themselves: clearly an intrusive pointer
|
||||
outperforms all others and a simple heap based counted pointer has poor performance
|
||||
relative to other implementations. The selection of an optimal non-intrusive
|
||||
smart pointer implementation is more application dependent, however. Where small
|
||||
numbers of copies are expected, it is likely that the linked implementation
|
||||
will be favoured. Conversely, for larger numbers of copies a counted pointer
|
||||
with some type of special purpose allocator looks like a win. Other factors
|
||||
to bear in mind are: -</p>
|
||||
<ul>
|
||||
<li>Deterministic individual, as opposed to amortized, operation time. This
|
||||
weighs against any implementation depending on an allocator.</li>
|
||||
<li>Multithreaded synchronization. This weighs against an implementation which
|
||||
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 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
|
||||
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>
|
220
weak_ptr.htm
Normal file
220
weak_ptr.htm
Normal file
@@ -0,0 +1,220 @@
|
||||
<!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>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.</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 <b>std::less<T *></b> 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 <b>std::less<></b> 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