mirror of
				https://github.com/boostorg/smart_ptr.git
				synced 2025-11-04 01:31:51 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			boost-1.25
			...
			boost-1.21
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					642e4f3b98 | 
							
								
								
									
										
											BIN
										
									
								
								gccspeed.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gccspeed.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 6.4 KiB  | 
							
								
								
									
										394
									
								
								include/boost/smart_ptr.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										394
									
								
								include/boost/smart_ptr.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,394 @@
 | 
			
		||||
//  Boost smart_ptr.hpp header file  -----------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
 | 
			
		||||
//  use, modify, sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided "as is"
 | 
			
		||||
//  without express or implied warranty, and with no claim as to its
 | 
			
		||||
//  suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 Jan 01  Suppress some useless warnings with MSVC (David Abrahams)
 | 
			
		||||
//  19 Oct 00  Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts) 
 | 
			
		||||
//  24 Jul 00  Change throw() to // never throws.  See lib guidelines
 | 
			
		||||
//             Exception-specification rationale. (Beman Dawes)
 | 
			
		||||
//  22 Jun 00  Remove #if continuations to fix GCC 2.95.2 problem (Beman Dawes)
 | 
			
		||||
//   1 Feb 00  Additional shared_ptr BOOST_NO_MEMBER_TEMPLATES workarounds
 | 
			
		||||
//             (Dave Abrahams)
 | 
			
		||||
//  31 Dec 99  Condition tightened for no member template friend workaround
 | 
			
		||||
//             (Dave Abrahams)
 | 
			
		||||
//  30 Dec 99  Moved BOOST_NMEMBER_TEMPLATES compatibility code to config.hpp
 | 
			
		||||
//             (Dave Abrahams)
 | 
			
		||||
//  30 Nov 99  added operator ==, operator !=, and std::swap and std::less
 | 
			
		||||
//             specializations for shared types (Darin Adler)
 | 
			
		||||
//  11 Oct 99  replaced op[](int) with op[](std::size_t) (Ed Brey, Valentin
 | 
			
		||||
//             Bonnard), added shared_ptr workaround for no member template
 | 
			
		||||
//             friends (Matthew Langston)
 | 
			
		||||
//  25 Sep 99  added shared_ptr::swap and shared_array::swap (Luis Coelho).
 | 
			
		||||
//  20 Jul 99  changed name to smart_ptr.hpp, #include <boost/config.hpp>,
 | 
			
		||||
//             #include <boost/utility.hpp> and use boost::noncopyable
 | 
			
		||||
//  17 May 99  remove scoped_array and shared_array operator*() as
 | 
			
		||||
//             unnecessary (Beman Dawes)
 | 
			
		||||
//  14 May 99  reorder code so no effects when bad_alloc thrown (Abrahams/Dawes)
 | 
			
		||||
//  13 May 99  remove certain throw() specifiers to avoid generated try/catch
 | 
			
		||||
//             code cost (Beman Dawes)
 | 
			
		||||
//  11 May 99  get() added, conversion to T* placed in macro guard (Valentin
 | 
			
		||||
//             Bonnard, Dave Abrahams, and others argued for elimination
 | 
			
		||||
//             of the automatic conversion)
 | 
			
		||||
//  28 Apr 99  #include <memory> fix (Valentin Bonnard)
 | 
			
		||||
//  28 Apr 99  rename transfer() to share() for clarity (Dave Abrahams)
 | 
			
		||||
//  28 Apr 99  remove unsafe shared_array template conversions(Valentin Bonnard)
 | 
			
		||||
//  28 Apr 99  p(r) changed to p(r.px) for clarity (Dave Abrahams)
 | 
			
		||||
//  21 Apr 99  reset() self assignment fix (Valentin Bonnard)
 | 
			
		||||
//  21 Apr 99  dispose() provided to improve clarity (Valentin Bonnard)
 | 
			
		||||
//  27 Apr 99  leak when new throws fixes (Dave Abrahams)
 | 
			
		||||
//  21 Oct 98  initial Version (Greg Colvin/Beman Dawes)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_SMART_PTR_HPP
 | 
			
		||||
#define BOOST_SMART_PTR_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>   // for broken compiler workarounds
 | 
			
		||||
#include <cstddef>            // for std::size_t
 | 
			
		||||
#include <memory>             // for std::auto_ptr
 | 
			
		||||
#include <algorithm>          // for std::swap
 | 
			
		||||
#include <boost/utility.hpp>  // for boost::noncopyable
 | 
			
		||||
#include <functional>         // for std::less
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
//  scoped_ptr  --------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  scoped_ptr mimics a built-in pointer except that it guarantees deletion
 | 
			
		||||
//  of the object pointed to, either on destruction of the scoped_ptr or via
 | 
			
		||||
//  an explicit reset().  scoped_ptr is a simple solution for simple needs;
 | 
			
		||||
//  see shared_ptr (below) or std::auto_ptr if your needs are more complex.
 | 
			
		||||
 | 
			
		||||
template<typename T> class scoped_ptr : noncopyable {
 | 
			
		||||
 | 
			
		||||
  T* ptr;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  typedef T element_type;
 | 
			
		||||
 | 
			
		||||
  explicit scoped_ptr( T* p=0 ) : ptr(p) {}  // never throws
 | 
			
		||||
  ~scoped_ptr()                 { delete ptr; }
 | 
			
		||||
 | 
			
		||||
  void reset( T* p=0 )          { if ( ptr != p ) { delete ptr; ptr = p; } }
 | 
			
		||||
  T& operator*() const          { return *ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
 | 
			
		||||
#endif    
 | 
			
		||||
  T* operator->() const         { return ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif    
 | 
			
		||||
  T* get() const                { return ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
  // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
  operator T*() const           { return ptr; }  // never throws 
 | 
			
		||||
#endif
 | 
			
		||||
  };  // scoped_ptr
 | 
			
		||||
 | 
			
		||||
//  scoped_array  ------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
 | 
			
		||||
//  is guaranteed, either on destruction of the scoped_array or via an explicit
 | 
			
		||||
//  reset(). See shared_array or std::vector if your needs are more complex.
 | 
			
		||||
 | 
			
		||||
template<typename T> class scoped_array : noncopyable {
 | 
			
		||||
 | 
			
		||||
  T* ptr;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  typedef T element_type;
 | 
			
		||||
 | 
			
		||||
  explicit scoped_array( T* p=0 ) : ptr(p) {}  // never throws
 | 
			
		||||
  ~scoped_array()                    { delete [] ptr; }
 | 
			
		||||
 | 
			
		||||
  void reset( T* p=0 )               { if ( ptr != p ) {delete [] ptr; ptr=p;} }
 | 
			
		||||
 | 
			
		||||
  T* get() const                     { return ptr; }  // never throws
 | 
			
		||||
#ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
  // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
  operator T*() const                { return ptr; }  // never throws
 | 
			
		||||
#else 
 | 
			
		||||
  T& operator[](std::size_t i) const { return ptr[i]; }  // never throws
 | 
			
		||||
#endif
 | 
			
		||||
  };  // scoped_array
 | 
			
		||||
 | 
			
		||||
//  shared_ptr  --------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  An enhanced relative of scoped_ptr with reference counted copy semantics.
 | 
			
		||||
//  The object pointed to is deleted when the last shared_ptr pointing to it
 | 
			
		||||
//  is destroyed or reset.
 | 
			
		||||
 | 
			
		||||
template<typename T> class shared_ptr {
 | 
			
		||||
  public:
 | 
			
		||||
   typedef T element_type;
 | 
			
		||||
 | 
			
		||||
   explicit shared_ptr(T* p =0) : px(p) {
 | 
			
		||||
      try { pn = new long(1); }  // fix: prevent leak if new throws
 | 
			
		||||
      catch (...) { delete p; throw; } 
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   shared_ptr(const shared_ptr& r) : px(r.px) { ++*(pn = r.pn); }  // never throws
 | 
			
		||||
 | 
			
		||||
   ~shared_ptr() { dispose(); }
 | 
			
		||||
 | 
			
		||||
   shared_ptr& operator=(const shared_ptr& r) {
 | 
			
		||||
      share(r.px,r.pn);
 | 
			
		||||
      return *this;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES )
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr(const shared_ptr<Y>& r) : px(r.px) {  // never throws 
 | 
			
		||||
         ++*(pn = r.pn); 
 | 
			
		||||
      }
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      explicit shared_ptr(std::auto_ptr<Y>& r) { 
 | 
			
		||||
         pn = new long(1); // may throw
 | 
			
		||||
         px = r.release(); // fix: moved here to stop leak if new throws
 | 
			
		||||
      }
 | 
			
		||||
#endif 
 | 
			
		||||
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& operator=(const shared_ptr<Y>& r) { 
 | 
			
		||||
         share(r.px,r.pn);
 | 
			
		||||
         return *this;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& operator=(std::auto_ptr<Y>& r) {
 | 
			
		||||
         // code choice driven by guarantee of "no effect if new throws"
 | 
			
		||||
         if (*pn == 1) { delete px; }
 | 
			
		||||
         else { // allocate new reference counter
 | 
			
		||||
           long * tmp = new long(1); // may throw
 | 
			
		||||
           --*pn; // only decrement once danger of new throwing is past
 | 
			
		||||
           pn = tmp;
 | 
			
		||||
         } // allocate new reference counter
 | 
			
		||||
         px = r.release(); // fix: moved here so doesn't leak if new throws 
 | 
			
		||||
         return *this;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
#else
 | 
			
		||||
#ifndef BOOST_NO_AUTO_PTR
 | 
			
		||||
      explicit shared_ptr(std::auto_ptr<T>& r) { 
 | 
			
		||||
         pn = new long(1); // may throw
 | 
			
		||||
         px = r.release(); // fix: moved here to stop leak if new throws
 | 
			
		||||
      } 
 | 
			
		||||
 | 
			
		||||
      shared_ptr& operator=(std::auto_ptr<T>& r) {
 | 
			
		||||
         // code choice driven by guarantee of "no effect if new throws"
 | 
			
		||||
         if (*pn == 1) { delete px; }
 | 
			
		||||
         else { // allocate new reference counter
 | 
			
		||||
           long * tmp = new long(1); // may throw
 | 
			
		||||
           --*pn; // only decrement once danger of new throwing is past
 | 
			
		||||
           pn = tmp;
 | 
			
		||||
         } // allocate new reference counter
 | 
			
		||||
         px = r.release(); // fix: moved here so doesn't leak if new throws 
 | 
			
		||||
         return *this;
 | 
			
		||||
      }
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   void reset(T* p=0) {
 | 
			
		||||
      if ( px == p ) return;  // fix: self-assignment safe
 | 
			
		||||
      if (--*pn == 0) { delete px; }
 | 
			
		||||
      else { // allocate new reference counter
 | 
			
		||||
        try { pn = new long; }  // fix: prevent leak if new throws
 | 
			
		||||
        catch (...) {
 | 
			
		||||
          ++*pn;  // undo effect of --*pn above to meet effects guarantee 
 | 
			
		||||
          delete p;
 | 
			
		||||
          throw;
 | 
			
		||||
        } // catch
 | 
			
		||||
      } // allocate new reference counter
 | 
			
		||||
      *pn = 1;
 | 
			
		||||
      px = p;
 | 
			
		||||
   } // reset
 | 
			
		||||
 | 
			
		||||
   T& operator*() const          { return *px; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(push)
 | 
			
		||||
# pragma warning(disable:4284) // return type for 'identifier::operator->' is not a UDT or reference to a UDT. Will produce errors if applied using infix notation
 | 
			
		||||
#endif    
 | 
			
		||||
   T* operator->() const         { return px; }  // never throws
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(pop)
 | 
			
		||||
#endif    
 | 
			
		||||
   T* get() const                { return px; }  // never throws
 | 
			
		||||
 #ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
   // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
   operator T*() const           { return px; }  // never throws 
 | 
			
		||||
 #endif
 | 
			
		||||
 | 
			
		||||
   long use_count() const        { return *pn; }  // never throws
 | 
			
		||||
   bool unique() const           { return *pn == 1; }  // never throws
 | 
			
		||||
 | 
			
		||||
   void swap(shared_ptr<T>& other)  // never throws
 | 
			
		||||
     { std::swap(px,other.px); std::swap(pn,other.pn); }
 | 
			
		||||
 | 
			
		||||
// Tasteless as this may seem, making all members public allows member templates
 | 
			
		||||
// to work in the absence of member template friends. (Matthew Langston)
 | 
			
		||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
 | 
			
		||||
#if defined(BOOST_NO_MEMBER_TEMPLATES) || !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
 | 
			
		||||
   private:
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   T*     px;     // contained pointer
 | 
			
		||||
   long*  pn;     // ptr to reference counter
 | 
			
		||||
 | 
			
		||||
// Don't split this line into two; that causes problems for some GCC 2.95.2 builds
 | 
			
		||||
#if !defined( BOOST_NO_MEMBER_TEMPLATES ) && !defined( BOOST_NO_MEMBER_TEMPLATE_FRIENDS )
 | 
			
		||||
   template<typename Y> friend class shared_ptr;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   void dispose() { if (--*pn == 0) { delete px; delete pn; } }
 | 
			
		||||
 | 
			
		||||
   void share(T* rpx, long* rpn) {
 | 
			
		||||
      if (pn != rpn) { // Q: why not px != rpx? A: fails when both == 0
 | 
			
		||||
         dispose();
 | 
			
		||||
         px = rpx;
 | 
			
		||||
         ++*(pn = rpn);
 | 
			
		||||
      }
 | 
			
		||||
   } // share
 | 
			
		||||
};  // shared_ptr
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
 | 
			
		||||
//  shared_array  ------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  shared_array extends shared_ptr to arrays.
 | 
			
		||||
//  The array pointed to is deleted when the last shared_array pointing to it
 | 
			
		||||
//  is destroyed or reset.
 | 
			
		||||
 | 
			
		||||
template<typename T> class shared_array {
 | 
			
		||||
  public:
 | 
			
		||||
   typedef T element_type;
 | 
			
		||||
 | 
			
		||||
   explicit shared_array(T* p =0) : px(p) {
 | 
			
		||||
      try { pn = new long(1); }  // fix: prevent leak if new throws
 | 
			
		||||
      catch (...) { delete [] p; throw; } 
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   shared_array(const shared_array& r) : px(r.px)  // never throws
 | 
			
		||||
      { ++*(pn = r.pn); }
 | 
			
		||||
 | 
			
		||||
   ~shared_array() { dispose(); }
 | 
			
		||||
 | 
			
		||||
   shared_array& operator=(const shared_array& r) {
 | 
			
		||||
      if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0
 | 
			
		||||
         dispose();
 | 
			
		||||
         px = r.px;
 | 
			
		||||
         ++*(pn = r.pn);
 | 
			
		||||
      }
 | 
			
		||||
      return *this;
 | 
			
		||||
   } // operator=
 | 
			
		||||
 | 
			
		||||
   void reset(T* p=0) {
 | 
			
		||||
      if ( px == p ) return;  // fix: self-assignment safe
 | 
			
		||||
      if (--*pn == 0) { delete [] px; }
 | 
			
		||||
      else { // allocate new reference counter
 | 
			
		||||
        try { pn = new long; }  // fix: prevent leak if new throws
 | 
			
		||||
        catch (...) {
 | 
			
		||||
          ++*pn;  // undo effect of --*pn above to meet effects guarantee 
 | 
			
		||||
          delete [] p;
 | 
			
		||||
          throw;
 | 
			
		||||
        } // catch
 | 
			
		||||
      } // allocate new reference counter
 | 
			
		||||
      *pn = 1;
 | 
			
		||||
      px = p;
 | 
			
		||||
   } // reset
 | 
			
		||||
 | 
			
		||||
   T* get() const                     { return px; }  // never throws
 | 
			
		||||
 #ifdef BOOST_SMART_PTR_CONVERSION
 | 
			
		||||
   // get() is safer! Define BOOST_SMART_PTR_CONVERSION at your own risk!
 | 
			
		||||
   operator T*() const                { return px; }  // never throws
 | 
			
		||||
 #else 
 | 
			
		||||
   T& operator[](std::size_t i) const { return px[i]; }  // never throws
 | 
			
		||||
 #endif
 | 
			
		||||
 | 
			
		||||
   long use_count() const             { return *pn; }  // never throws
 | 
			
		||||
   bool unique() const                { return *pn == 1; }  // never throws
 | 
			
		||||
 | 
			
		||||
   void swap(shared_array<T>& other)  // never throws
 | 
			
		||||
     { std::swap(px,other.px); std::swap(pn,other.pn); }
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
 | 
			
		||||
   T*     px;     // contained pointer
 | 
			
		||||
   long*  pn;     // ptr to reference counter
 | 
			
		||||
 | 
			
		||||
   void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
 | 
			
		||||
 | 
			
		||||
};  // shared_array
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
//  specializations for things in namespace std  -----------------------------//
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
namespace std {
 | 
			
		||||
 | 
			
		||||
// Specialize std::swap to use the fast, non-throwing swap that's provided
 | 
			
		||||
// as a member function instead of using the default algorithm which creates
 | 
			
		||||
// a temporary and uses assignment.
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
// Specialize std::less so we can use shared pointers and arrays as keys in
 | 
			
		||||
// associative collections.
 | 
			
		||||
 | 
			
		||||
// It's still a controversial question whether this is better than supplying
 | 
			
		||||
// a full range of comparison operators (<, >, <=, >=).
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_ptr<T> >
 | 
			
		||||
    : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_ptr<T>& a,
 | 
			
		||||
        const boost::shared_ptr<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_array<T> >
 | 
			
		||||
    : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_array<T>& a,
 | 
			
		||||
        const boost::shared_array<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
} // namespace std
 | 
			
		||||
 | 
			
		||||
#endif  // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_SMART_PTR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										38
									
								
								index.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								index.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
<title>Boost Smart Pointer Library</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<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 header smart_ptr.hpp provides four smart pointer classes.  Smart
 | 
			
		||||
pointers ease the management of memory dynamically allocated with C++ <strong>new</strong>
 | 
			
		||||
expressions.
 | 
			
		||||
<ul>
 | 
			
		||||
  <li><a href="smart_ptr.htm">Documentation</a> (HTML).</li>
 | 
			
		||||
  <li>Header <a href="../../boost/smart_ptr.hpp">smart_ptr.hpp</a></li>
 | 
			
		||||
  <li>Test program <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.</li>
 | 
			
		||||
  <li>Submitted by <a href="../../people/greg_colvin.htm">Greg Colvin</a> and <a href="../../people/beman_dawes.html">Beman
 | 
			
		||||
    Dawes</a>.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->14 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14885" -->
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								msvcspeed.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								msvcspeed.gif
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 6.0 KiB  | 
							
								
								
									
										90
									
								
								scoped_array.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								scoped_array.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<title>scoped_array</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="scoped_array">scoped_array</a></h1>
 | 
			
		||||
<p>Class <strong>scoped_array</strong> stores a pointer to a dynamically
 | 
			
		||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
 | 
			
		||||
expression.)   The array pointed to is guaranteed to be deleted,
 | 
			
		||||
either on destruction of the <strong>scoped_array</strong>, or via an explicit <strong>scoped_array::reset()</strong>.</p>
 | 
			
		||||
<p>Class<strong> scoped_array</strong> is a simple solution for simple
 | 
			
		||||
needs.  It cannot be used in C++ Standard Library containers.  See <a href="shared_array.htm"><strong>shared_array</strong></a>
 | 
			
		||||
if <strong>scoped_array</strong> does not meet your needs.</p>
 | 
			
		||||
<p>Class<strong> scoped_array</strong> cannot correctly hold a pointer to a
 | 
			
		||||
single object.  See <a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Because <strong>scoped_array</strong> is so simple, in its usual
 | 
			
		||||
implementation every operation is as fast as a built-in array pointer and has no
 | 
			
		||||
more space overhead that a built-in array pointer.</p>
 | 
			
		||||
<p>A heavier duty alternative to a <strong>scoped_array</strong> is a <strong>scoped_ptr</strong>
 | 
			
		||||
to a C++ Standard Library <strong>vector</strong>.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class scoped_array Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
template<typename T> class scoped_array : <a href="../utility/utility.htm#noncopyable">noncopyable</a> {
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#scoped_array_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
   explicit <a href="#scoped_array_ctor">scoped_array</a>( T* p=0 );  // never throws
 | 
			
		||||
  <strong> </strong><a href="#scoped_array_~scoped_array">~scoped_array</a>();
 | 
			
		||||
 | 
			
		||||
   void <a href="#scoped_array_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
   T& <a href="#scoped_array_operator[]">operator[]</a>(std::size_t i) const;  // never throws
 | 
			
		||||
   T* <a href="#scoped_array_get">get</a>() const;  // never throws
 | 
			
		||||
   };
 | 
			
		||||
}</pre>
 | 
			
		||||
<h2>Class scoped_array Members</h2>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="scoped_array_ctor">scoped_array constructors</a></h3>
 | 
			
		||||
<pre>explicit scoped_array( T* p=0 );  // never throws</pre>
 | 
			
		||||
<p>Constructs a <tt>scoped_array</tt>, storing a copy of <tt>p</tt>, which must
 | 
			
		||||
have been allocated via a C++ <tt>new</tt>[] expression or be 0.</p>
 | 
			
		||||
<h3><a name="scoped_array_~scoped_array">scoped_array destructor</a></h3>
 | 
			
		||||
<pre>~scoped_array();</pre>
 | 
			
		||||
<p>Deletes the array pointed to by the stored pointer.  Note that in C++ <tt>delete</tt>[]
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 )();</pre>
 | 
			
		||||
<p>If p is not equal to the stored pointer, deletes the array pointed to by the
 | 
			
		||||
stored pointer and then stores a copy of p, which must have been allocated via a
 | 
			
		||||
C++ <tt>new[]</tt> expression or be 0.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_operator[]">operator[]</a></h3>
 | 
			
		||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
 | 
			
		||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
 | 
			
		||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
 | 
			
		||||
in the array.</p>
 | 
			
		||||
<h3>scoped_array <a name="scoped_array_get">get</a></h3>
 | 
			
		||||
<pre>T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Returns the stored pointer.</p>
 | 
			
		||||
<h2>Class <a name="shared_array_example">scoped_array example</a></h2>
 | 
			
		||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  December 8, 1999</p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										128
									
								
								scoped_ptr.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								scoped_ptr.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<title>scoped_ptr</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="scoped_ptr">scoped_ptr</a></h1>
 | 
			
		||||
<p>Class <strong>scoped_ptr</strong> stores a pointer to a dynamically allocated
 | 
			
		||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
 | 
			
		||||
expression.)   The object pointed to is guaranteed to be deleted,
 | 
			
		||||
either on destruction of the <strong>scoped_ptr</strong>, or via an explicit <strong>scoped_ptr::reset()</strong>. 
 | 
			
		||||
See <a href="#scoped_ptr_example">example</a>.</p>
 | 
			
		||||
<p>Class<strong> scoped_ptr</strong> is a simple solution for simple
 | 
			
		||||
needs.  It cannot be used in C++ Standard Library containers.  See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
 | 
			
		||||
or std::auto_ptr if <strong>scoped_ptr</strong> does not meet your needs.</p>
 | 
			
		||||
<p>Class<strong> scoped_ptr</strong> cannot correctly hold a pointer to a
 | 
			
		||||
dynamically allocated array.  See <a href="scoped_array.htm"><strong>scoped_array</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Because <strong>scoped_ptr</strong> is so simple, in its usual implementation
 | 
			
		||||
every operation is as fast as a built-in pointer and has no more space overhead
 | 
			
		||||
that a built-in pointer.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class scoped_ptr Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
template<typename T> class scoped_ptr : <a href="../utility/utility.htm#class noncopyable">noncopyable</a> {
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#scoped_ptr_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
   explicit <a href="#scoped_ptr_ctor">scoped_ptr</a>( T* p=0 );  // never throws
 | 
			
		||||
  <strong> </strong><a href="#scoped_ptr_~scoped_ptr">~scoped_ptr</a>();
 | 
			
		||||
 | 
			
		||||
   void <a href="#scoped_ptr_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
   T& <a href="#scoped_ptr_operator*">operator*</a>() const;  // never throws
 | 
			
		||||
   T* <a href="#scoped_ptr_operator->">operator-></a>() const;  // never throws
 | 
			
		||||
   T* <a href="#scoped_ptr_get">get</a>() const;  // never throws
 | 
			
		||||
   };
 | 
			
		||||
}</pre>
 | 
			
		||||
<h2>Class scoped_ptr Members</h2>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="scoped_ptr_ctor">scoped_ptr constructors</a></h3>
 | 
			
		||||
<pre>explicit scoped_ptr( T* p=0 );  // never throws</pre>
 | 
			
		||||
<p>Constructs a <tt>scoped_ptr</tt>, storing a copy of <tt>p</tt>, which must
 | 
			
		||||
have been allocated via a C++ <tt>new</tt> expression or be 0..</p>
 | 
			
		||||
<h3><a name="scoped_ptr_~scoped_ptr">scoped_ptr destructor</a></h3>
 | 
			
		||||
<pre>~scoped_ptr();</pre>
 | 
			
		||||
<p>Deletes the object pointed to by the stored pointer.  Note that in C++, <tt>delete</tt>
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 );</pre>
 | 
			
		||||
<p>If p is not equal to the stored pointer, deletes the object pointed to by the
 | 
			
		||||
stored pointer and then stores a copy of p, which must have been allocated via a
 | 
			
		||||
C++ <tt>new</tt> expression or be 0.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_operator*">operator*</a></h3>
 | 
			
		||||
<pre>T& operator*() const;  // never throws</pre>
 | 
			
		||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
 | 
			
		||||
<h3>scoped_ptr <a name="scoped_ptr_operator->">operator-></a> and <a name="scoped_ptr_get">get</a></h3>
 | 
			
		||||
<pre>T* operator->() const;  // never throws
 | 
			
		||||
T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Both return the stored pointer.</p>
 | 
			
		||||
<h2>Class <a name="scoped_ptr_example">scoped_ptr example</a>s</h2>
 | 
			
		||||
<pre>#include <iostream>
 | 
			
		||||
#include <boost/smart_ptr.h>
 | 
			
		||||
 | 
			
		||||
struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } };
 | 
			
		||||
 | 
			
		||||
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() << std::endl;
 | 
			
		||||
    std::cout << my_instance.add_one() << std::endl;
 | 
			
		||||
    }</pre>
 | 
			
		||||
<p>The example program produces the beginning of a child's nursery rhyme as
 | 
			
		||||
output:</p>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>1
 | 
			
		||||
2
 | 
			
		||||
Buckle my shoe</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h2>Handle/Body Idiom</h2>
 | 
			
		||||
<p>One common usage of <b>shared_pointer</b> is to implement a handle/body
 | 
			
		||||
structure which avoids exposing the body (implementation) in the header file:</p>
 | 
			
		||||
<pre>class handle
 | 
			
		||||
{
 | 
			
		||||
public:    // simple forwarding functions to the body class
 | 
			
		||||
    void f();
 | 
			
		||||
    void g(int);
 | 
			
		||||
private:
 | 
			
		||||
    friend class body;  //incomplete class hides implementation
 | 
			
		||||
    boost::scoped_ptr<body> imp;
 | 
			
		||||
};</pre>
 | 
			
		||||
<p>This code requires that <code>class body</code> have a trivial destructor to
 | 
			
		||||
avoid undefined behavior.  This is because the definition of <code>class
 | 
			
		||||
body</code> is not visible at the time scoped_ptr<> deletes it. See ISO
 | 
			
		||||
5.3.5/5.  Note that some compilers will issue a warning even though the
 | 
			
		||||
above code is well defined.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->27 July 2000<!--webbot bot="Timestamp" endspan i-checksum="18770" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										180
									
								
								shared_array.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								shared_array.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,180 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<title>shared_array</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="shared_array">shared_array</a></h1>
 | 
			
		||||
<p>Class <strong>shared_array</strong> stores a pointer to a dynamically
 | 
			
		||||
allocated array. (Dynamically allocated arrays are allocated with the C++ <tt>new[]</tt>
 | 
			
		||||
expression.)   The array pointed to is guaranteed to be deleted,
 | 
			
		||||
either on destruction of the <strong>shared_array</strong>, on <strong>shared_array::operator=()</strong>,
 | 
			
		||||
or via an explicit <strong>shared_array::reset()</strong>.  See <a href="#shared_array_example">example</a>.</p>
 | 
			
		||||
<p>Class<strong> shared_array</strong> meets the <strong>CopyConstuctible</strong>
 | 
			
		||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
 | 
			
		||||
can be used in C++ Standard Library containers.  A specialization of std::
 | 
			
		||||
less< > for  boost::shared_ptr<Y> is supplied so that <strong>
 | 
			
		||||
shared_array</strong> works by default for Standard Library's Associative
 | 
			
		||||
Container Compare template parameter.  For compilers not supporting partial
 | 
			
		||||
specialization, the user must explicitly pass the less<> functor.</p>
 | 
			
		||||
<p>Class<strong> shared_array</strong> cannot correctly hold a pointer to a
 | 
			
		||||
single object.  See <a href="shared_ptr.htm"><strong>shared_ptr</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Class<strong> shared_array</strong> will not work correctly with cyclic data
 | 
			
		||||
structures. For example, if main() holds a shared_array pointing to array A,
 | 
			
		||||
which directly or indirectly holds a shared_array pointing back to array A, then
 | 
			
		||||
array A's use_count() will be 2, and destruction of the main() shared_array will
 | 
			
		||||
leave array A dangling with a use_count() of 1.</p>
 | 
			
		||||
<p>A heavier duty alternative to a <strong>shared_array</strong> is a <strong>shared_ptr</strong>
 | 
			
		||||
to a C++ Standard Library <strong>vector</strong>.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class shared_array Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
template<typename T> class shared_array {
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#shared_array_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
   explicit <a href="#shared_array_ctor">shared_array</a>( T* p=0 );
 | 
			
		||||
   <a href="#shared_array_ctor">shared_array</a>( const shared_array& );  // never throws   
 | 
			
		||||
  <strong> </strong><a href="#shared_array_~shared_array">~shared_array</a>();
 | 
			
		||||
 | 
			
		||||
   shared_array& <a href="#shared_array_operator=">operator=</a>( const shared_array& );  // never throws  
 | 
			
		||||
 | 
			
		||||
   void <a href="#shared_array_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
   T& <a href="#shared_array_operator[]">operator[]</a>(std::size_t i) const;  // never throws
 | 
			
		||||
   T* <a href="#shared_array_get">get</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
   long <a href="#shared_array_use_count">use_count</a>() const;  // never throws
 | 
			
		||||
   bool <a href="#shared_array_unique">unique</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
   void <a href="#shared_array_swap">swap</a>( shared_array<T>& other ) throw()
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
}</pre>
 | 
			
		||||
<pre>namespace std {
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_array<T> >
 | 
			
		||||
    : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_array<T>& a,
 | 
			
		||||
        const boost::shared_array<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
} // namespace std </pre>
 | 
			
		||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
 | 
			
		||||
as a member function instead of using the default algorithm which creates a
 | 
			
		||||
temporary and uses assignment.<br>
 | 
			
		||||
<br>
 | 
			
		||||
Specialization of std::less allows use of shared arrays as keys in C++
 | 
			
		||||
Standard Library associative collections.<br>
 | 
			
		||||
<br>
 | 
			
		||||
The std::less specializations use std::less<T*> to perform the
 | 
			
		||||
comparison.  This insures that pointers are handled correctly, since the
 | 
			
		||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
 | 
			
		||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
 | 
			
		||||
paragraph 8).<br>
 | 
			
		||||
<br>
 | 
			
		||||
It's still a controversial question whether supplying only std::less is better
 | 
			
		||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
 | 
			
		||||
<p>The current implementation does not supply the specializations if the macro
 | 
			
		||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
 | 
			
		||||
<h2>Class shared_array Members</h2>
 | 
			
		||||
<h3>shared_array <a name="shared_array_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="shared_array_ctor">shared_array constructors</a></h3>
 | 
			
		||||
<pre>explicit shared_array( T* p=0 );</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_array</strong>, storing a copy of <tt>p</tt>,
 | 
			
		||||
which must have been allocated via a C++ <tt>new</tt>[] expression or be 0.
 | 
			
		||||
Afterwards, use_count() is 1 (even if p==0; see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
 | 
			
		||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.  If
 | 
			
		||||
an exception is thrown,  <tt>delete[] p</tt> is called.</p>
 | 
			
		||||
<pre>shared_array( const shared_array& r);  // never throws</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_array</strong>, as if by storing a copy of the
 | 
			
		||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>.</p>
 | 
			
		||||
<h3><a name="shared_array_~shared_array">shared_array destructor</a></h3>
 | 
			
		||||
<pre>~shared_array();</pre>
 | 
			
		||||
<p>If <strong>use_count()</strong> == 1, deletes the array pointed to by the
 | 
			
		||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
 | 
			
		||||
copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a pointer with
 | 
			
		||||
a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_operator=">operator=</a></h3>
 | 
			
		||||
<pre>shared_array& operator=( const shared_array& r);  // never throws</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. Note that in C++ <tt>delete</tt>[] on a
 | 
			
		||||
pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>. </p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 );</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the array pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. Note that in C++  <tt>delete</tt>[]
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of <strong>p</strong>, which must have been allocated via a C++ <tt>new</tt>[]
 | 
			
		||||
expression or be 0. Afterwards, <strong>use_count()</strong> is 1 (even if p==0;
 | 
			
		||||
see <a href="#shared_array_~shared_array">~shared_array</a>).</p>
 | 
			
		||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.  If
 | 
			
		||||
an exception is thrown,  <tt>delete[] p</tt> is called.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_operator[]">operator[]</a></h3>
 | 
			
		||||
<p><tt>T& operator[](std::size_t i) const; // never throws</tt></p>
 | 
			
		||||
<p>Returns a reference to element <tt>i</tt> of the array pointed to by the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<p>Behavior is undefined (and almost certainly undesirable) if <tt>get()==0</tt>,
 | 
			
		||||
or if <tt>i</tt> is less than 0 or is greater or equal to the number of elements
 | 
			
		||||
in the array.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_get">get</a></h3>
 | 
			
		||||
<pre>T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Returns the stored pointer.</p>
 | 
			
		||||
<h3>shared_array<a name="shared_array_use_count"> use_count</a></h3>
 | 
			
		||||
<p><tt>long use_count() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns the number of <strong>shared_arrays</strong> sharing ownership of the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<h3>shared_array <a name="shared_array_unique">unique</a></h3>
 | 
			
		||||
<p><tt>bool unique() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns <strong>use_count()</strong> == 1.</p>
 | 
			
		||||
<h3><a name="shared_array_swap">shared_array swap</a></h3>
 | 
			
		||||
<p><code>void swap( shared_array<T>& other ) throw()</code></p>
 | 
			
		||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
 | 
			
		||||
<h2>Class <a name="shared_array_example">shared_array example</a></h2>
 | 
			
		||||
<p>[To be supplied. In the meantime, see <a href="smart_ptr_test.cpp">smart_ptr_test.cpp</a>.]</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised December 8, 1999</p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										231
									
								
								shared_ptr.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								shared_ptr.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,231 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<title>shared_ptr</title>
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Class
 | 
			
		||||
<a name="shared_ptr">shared_ptr</a></h1>
 | 
			
		||||
<p>Class <strong>shared_ptr</strong> stores a pointer to a dynamically allocated
 | 
			
		||||
object. (Dynamically allocated objects are allocated with the C++ <tt>new</tt>
 | 
			
		||||
expression.)   The object pointed to is guaranteed to be deleted when
 | 
			
		||||
the last <strong>shared_ptr</strong> pointing to it is deleted or reset. 
 | 
			
		||||
See <a href="#shared_ptr_example">example</a>.</p>
 | 
			
		||||
<p>Class<strong> shared_ptr</strong> meets the <strong>CopyConstuctible</strong>
 | 
			
		||||
and <strong>Assignable</strong> requirements of the C++ Standard Library, and so
 | 
			
		||||
can be used in C++ Standard Library containers.  A specialization of std::
 | 
			
		||||
less< > for  boost::shared_ptr<Y> is supplied so that <strong>
 | 
			
		||||
shared_ptr</strong> works by default for Standard Library's Associative
 | 
			
		||||
Container Compare template parameter.  For compilers not supporting partial
 | 
			
		||||
specialization, the user must explicitly pass the less<> functor.</p>
 | 
			
		||||
<p>Class<strong> shared_ptr</strong> cannot correctly hold a pointer to a
 | 
			
		||||
dynamically allocated array.  See <a href="shared_array.htm"><strong>shared_array</strong></a>
 | 
			
		||||
for that usage.</p>
 | 
			
		||||
<p>Class<strong> shared_ptr</strong> will not work correctly with cyclic data
 | 
			
		||||
structures. For example, if main() holds a shared_ptr to object A, which
 | 
			
		||||
directly or indirectly holds a shared_ptr back to object A, then object A's
 | 
			
		||||
use_count() will be 2, and destruction of the main() shared_ptr will leave
 | 
			
		||||
object A dangling with a use_count() of 1.</p>
 | 
			
		||||
<p>The class is a template parameterized on <tt>T</tt>, the type of the object
 | 
			
		||||
pointed to.   <tt>T</tt> must meet the smart pointer <a href="smart_ptr.htm#Common requirements">Common
 | 
			
		||||
requirements</a>.</p>
 | 
			
		||||
<h2>Class shared_ptr Synopsis</h2>
 | 
			
		||||
<pre>#include <boost/smart_ptr.hpp>
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
template<typename T> class shared_ptr {
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
   typedef T <a href="#shared_ptr_element_type">element_type</a>;
 | 
			
		||||
 | 
			
		||||
   explicit <a href="#shared_ptr_ctor">shared_ptr</a>( T* p=0 );
 | 
			
		||||
  <strong> </strong><a href="#shared_ptr_~shared_ptr">~shared_ptr</a>();
 | 
			
		||||
 | 
			
		||||
   <a href="#shared_ptr_ctor">shared_ptr</a>( const shared_ptr& );   
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      <a href="#shared_ptr_ctor">shared_ptr</a>(const shared_ptr<Y>& r);  // never throws
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      <a href="#shared_ptr_ctor">shared_ptr</a>(std::auto_ptr<Y>& r);
 | 
			
		||||
 | 
			
		||||
   shared_ptr& <a href="#shared_ptr_operator=">operator=</a>( const shared_ptr& );  // never throws  
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(const shared_ptr<Y>& r);  // never throws
 | 
			
		||||
   template<typename Y>
 | 
			
		||||
      shared_ptr& <a href="#shared_ptr_operator=">operator=</a>(std::auto_ptr<Y>& r);
 | 
			
		||||
 | 
			
		||||
   void <a href="#shared_ptr_reset">reset</a>( T* p=0 );
 | 
			
		||||
 | 
			
		||||
   T& <a href="#shared_ptr_operator*">operator*</a>() const;  // never throws
 | 
			
		||||
   T* <a href="#shared_ptr_operator->">operator-></a>() const;  // never throws
 | 
			
		||||
   T* <a href="#shared_ptr_get">get</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
   long <a href="#shared_ptr_use_count">use_count</a>() const;  // never throws
 | 
			
		||||
   bool <a href="#shared_ptr_unique">unique</a>() const;  // never throws
 | 
			
		||||
 | 
			
		||||
   void <a href="#shared_ptr_swap">swap</a>( shared_ptr<T>& other ) throw()
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() == b.get(); }
 | 
			
		||||
 | 
			
		||||
template<typename T, typename U>
 | 
			
		||||
  inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b)
 | 
			
		||||
    { return a.get() != b.get(); }
 | 
			
		||||
}</pre>
 | 
			
		||||
<pre>namespace std {
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b)
 | 
			
		||||
    { a.swap(b); }
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
  struct less< boost::shared_ptr<T> >
 | 
			
		||||
    : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool>
 | 
			
		||||
  {
 | 
			
		||||
    bool operator()(const boost::shared_ptr<T>& a,
 | 
			
		||||
        const boost::shared_ptr<T>& b) const
 | 
			
		||||
      { return less<T*>()(a.get(),b.get()); }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
} // namespace std </pre>
 | 
			
		||||
<p>Specialization of std::swap uses the fast, non-throwing swap that's provided
 | 
			
		||||
as a member function instead of using the default algorithm which creates a
 | 
			
		||||
temporary and uses assignment.<br>
 | 
			
		||||
<br>
 | 
			
		||||
Specialization of std::less allows use of shared pointers as keys in C++
 | 
			
		||||
Standard Library associative collections.<br>
 | 
			
		||||
<br>
 | 
			
		||||
The std::less specializations use std::less<T*> to perform the
 | 
			
		||||
comparison.  This insures that pointers are handled correctly, since the
 | 
			
		||||
standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel]
 | 
			
		||||
paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons]
 | 
			
		||||
paragraph 8).<br>
 | 
			
		||||
<br>
 | 
			
		||||
It's still a controversial question whether supplying only std::less is better
 | 
			
		||||
than supplying a full range of comparison operators (<, >, <=, >=).</p>
 | 
			
		||||
<p>The current implementation does not supply the specializations if the macro
 | 
			
		||||
name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.</p>
 | 
			
		||||
<p>The current implementation does not supply the member template functions if
 | 
			
		||||
the macro name BOOST_NO_MEMBER_TEMPLATES is defined.</p>
 | 
			
		||||
<h2>Class shared_ptr Members</h2>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_element_type">element_type</a></h3>
 | 
			
		||||
<pre>typedef T element_type;</pre>
 | 
			
		||||
<p>Provides the type of the stored pointer.</p>
 | 
			
		||||
<h3><a name="shared_ptr_ctor">shared_ptr constructors</a></h3>
 | 
			
		||||
<pre>explicit shared_ptr( T* p=0 );</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_ptr</strong>, storing a copy of <tt>p</tt>, which
 | 
			
		||||
must have been allocated via a C++ <tt>new</tt> expression or be 0. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
is 1 (even if p==0; see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>).</p>
 | 
			
		||||
<p>The only exception which may be thrown by this constructor is <tt>std::bad_alloc</tt>.  
 | 
			
		||||
If an exception is thrown,  <tt>delete p</tt> is called.</p>
 | 
			
		||||
<pre>shared_ptr( const shared_ptr& r);  // never throws   
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr(const shared_ptr<Y>& r);  // never throws
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr(std::auto_ptr<Y>& r);</pre>
 | 
			
		||||
<p>Constructs a <strong>shared_ptr</strong>, as if by storing a copy of the
 | 
			
		||||
pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
 | 
			
		||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
 | 
			
		||||
is called.</p>
 | 
			
		||||
<p>The only exception which may be thrown by the constructor from <strong>auto_ptr</strong>
 | 
			
		||||
is <tt>std::bad_alloc</tt>.   If an exception is thrown, that
 | 
			
		||||
constructor has no effect.</p>
 | 
			
		||||
<h3><a name="shared_ptr_~shared_ptr">shared_ptr destructor</a></h3>
 | 
			
		||||
<pre>~shared_ptr();</pre>
 | 
			
		||||
<p>If <strong>use_count()</strong> == 1, deletes the object pointed to by the
 | 
			
		||||
stored pointer. Otherwise, <strong>use_count()</strong> for any remaining
 | 
			
		||||
copies is decremented by 1. Note that in C++  <tt>delete</tt> on a pointer
 | 
			
		||||
with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Does not throw exceptions.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_operator=">operator=</a></h3>
 | 
			
		||||
<pre>shared_ptr& operator=( const shared_ptr& r);  
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr& operator=(const shared_ptr<Y>& r);
 | 
			
		||||
template<typename Y>
 | 
			
		||||
   shared_ptr& operator=(std::auto_ptr<Y>& r);</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. Note that in C++  <tt>delete</tt> on
 | 
			
		||||
a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of the pointer stored in <strong>r</strong>. Afterwards, <strong>use_count()</strong>
 | 
			
		||||
for all copies is 1 more than the initial <strong>r.use_count()</strong>, or 1
 | 
			
		||||
in the <strong>auto_ptr</strong> case. In the <strong>auto_ptr</strong> case, <strong>r.release()</strong>
 | 
			
		||||
is called.</p>
 | 
			
		||||
<p>The first two forms of <tt>operator=</tt> above do not throw exceptions.</p>
 | 
			
		||||
<p>The only exception which may be thrown by the <strong>auto_ptr</strong> form
 | 
			
		||||
is <tt>std::bad_alloc</tt>.   If an exception is thrown, the function
 | 
			
		||||
has no effect.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_reset">reset</a></h3>
 | 
			
		||||
<pre>void reset( T* p=0 );</pre>
 | 
			
		||||
<p>First, if <strong>use_count()</strong> == 1, deletes the object pointed to by
 | 
			
		||||
the stored pointer. Otherwise, <strong>use_count()</strong> for any
 | 
			
		||||
remaining copies is decremented by 1. </p>
 | 
			
		||||
<p>Then replaces the contents of <strong>this</strong>, as if by storing a copy
 | 
			
		||||
of <strong>p</strong>, which must have been allocated via a C++ <tt>new</tt>
 | 
			
		||||
expression or be 0. Afterwards, <strong>use_count()</strong> is 1 (even if p==0;
 | 
			
		||||
see <a href="#shared_ptr_~shared_ptr">~shared_ptr</a>). Note that in C++  <tt>delete</tt>
 | 
			
		||||
on a pointer with a value of 0 is harmless.</p>
 | 
			
		||||
<p>The only exception which may be thrown is <tt>std::bad_alloc</tt>.  If
 | 
			
		||||
an exception is thrown,  <tt>delete p</tt> is called.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_operator*">operator*</a></h3>
 | 
			
		||||
<pre>T& operator*() const;  // never throws</pre>
 | 
			
		||||
<p>Returns a reference to the object pointed to by the stored pointer.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_operator->">operator-></a> and <a name="shared_ptr_get">get</a></h3>
 | 
			
		||||
<pre>T* operator->() const;  // never throws
 | 
			
		||||
T* get() const;  // never throws</pre>
 | 
			
		||||
<p>Both return the stored pointer.</p>
 | 
			
		||||
<h3>shared_ptr<a name="shared_ptr_use_count"> use_count</a></h3>
 | 
			
		||||
<p><tt>long use_count() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns the number of <strong>shared_ptrs</strong> sharing ownership of the
 | 
			
		||||
stored pointer.</p>
 | 
			
		||||
<h3>shared_ptr <a name="shared_ptr_unique">unique</a></h3>
 | 
			
		||||
<p><tt>bool unique() const; // never throws</tt></p>
 | 
			
		||||
<p>Returns <strong>use_count()</strong> == 1.</p>
 | 
			
		||||
<h3><a name="shared_ptr_swap">shared_ptr swap</a></h3>
 | 
			
		||||
<p><code>void swap( shared_ptr<T>& other ) throw()</code></p>
 | 
			
		||||
<p>Swaps the two smart pointers, as if by std::swap.</p>
 | 
			
		||||
<h2>Class <a name="shared_ptr_example">shared_ptr example</a></h2>
 | 
			
		||||
<pre>//  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).
 | 
			
		||||
 | 
			
		||||
class Foo { ... };
 | 
			
		||||
 | 
			
		||||
typedef boost::shared_ptr<Foo> FooPtr;
 | 
			
		||||
 | 
			
		||||
std::vector<FooPtr> foo_vector;
 | 
			
		||||
std::set<FooPtr>    foo_set; // NOT multiset!
 | 
			
		||||
 | 
			
		||||
...
 | 
			
		||||
{ // creation loop
 | 
			
		||||
  FooPtr foo_ptr ( new Foo( ... ) );
 | 
			
		||||
  foo_vector.push_back( foo_ptr );
 | 
			
		||||
  foo_set.insert( foo_ptr );
 | 
			
		||||
}</pre>
 | 
			
		||||
<p>Note that at the termination of the creation loop, some of the FooPtr objects
 | 
			
		||||
may have use_count()==1 rather than use_count()==2, since foo_set is a std::set
 | 
			
		||||
rather than a std::multiset.  Furthermore, use_count() will be even higher
 | 
			
		||||
at various times inside the loop, as container operations are performed. 
 | 
			
		||||
More complicated yet, the container operations may throw exceptions under a
 | 
			
		||||
variety of circumstances.  Without using a smart pointer, memory and
 | 
			
		||||
exception management would be a nightmare.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->10 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40395" -->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										138
									
								
								smart_ptr.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								smart_ptr.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,138 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Smart Pointer Classes</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Smart
 | 
			
		||||
Pointers</h1>
 | 
			
		||||
<p>Smart pointers are classes which store pointers to dynamically allocated
 | 
			
		||||
(heap) objects.  They behave much like built-in C++ pointers except that
 | 
			
		||||
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 header <a href="../../boost/smart_ptr.hpp">boost/smart_ptr.hpp</a>
 | 
			
		||||
provides four smart pointer template classes:</p>
 | 
			
		||||
<div align="left">
 | 
			
		||||
  <table border="1" cellpadding="4" cellspacing="4">
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td>
 | 
			
		||||
        <p align="left"><a href="scoped_ptr.htm"><strong>scoped_ptr</strong></a></td>
 | 
			
		||||
      <td>Simple sole ownership of single objects.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td><a href="scoped_array.htm"><strong>scoped_array</strong></a></td>
 | 
			
		||||
      <td>Simple sole ownership of arrays.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td><a href="shared_ptr.htm"><strong>shared_ptr</strong></a></td>
 | 
			
		||||
      <td>Object ownership shared among multiple pointers</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <td><a href="shared_array.htm"><strong>shared_array</strong></a></td>
 | 
			
		||||
      <td>Array ownership shared among multiple pointers.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
  </table>
 | 
			
		||||
</div>
 | 
			
		||||
<p>These classes are designed to complement the C++ Standard Library <tt>auto_ptr</tt>
 | 
			
		||||
class.</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="smarttests.htm">Smart Pointer Timings</a> will be of
 | 
			
		||||
interest to those curious about performance issues.</p>
 | 
			
		||||
<h2><a name="Common requirements">Common requirements</a></h2>
 | 
			
		||||
<p>These smart pointer classes have a template parameter, <tt>T</tt>, which
 | 
			
		||||
specifies the type of the object pointed to by the smart pointer.  The
 | 
			
		||||
behavior of all four classes is undefined if the destructor or operator delete
 | 
			
		||||
for objects of type <tt>T</tt> throws exceptions.</p>
 | 
			
		||||
<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 <tt>T</tt> meets the <a href="#Common requirements">Common
 | 
			
		||||
requirements</a>)  is <tt>std::bad_alloc</tt>, and that is thrown only by
 | 
			
		||||
functions which are explicitly documented as possibly throwing <tt>std::bad_alloc</tt>.</p>
 | 
			
		||||
<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 four classes contain member functions which can never throw exceptions,
 | 
			
		||||
because they neither throw exceptions themselves nor call other functions which
 | 
			
		||||
may throw exceptions.  These members are indicated by a comment: <kbd>//
 | 
			
		||||
never throws</kbd>. </p>
 | 
			
		||||
<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>November, 1999. Darin Adler provided operator ==, operator !=, and std::swap
 | 
			
		||||
and std::less specializations for shared types.</p>
 | 
			
		||||
<p>September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap</p>
 | 
			
		||||
<p>May, 1999.  In April and May, 1999, Valentin Bonnard and David Abrahams
 | 
			
		||||
made a number of suggestions resulting in numerous improvements.  See the
 | 
			
		||||
revision history in <a href="../../boost/smart_ptr.hpp"><tt>smart_ptr.hpp</tt></a>
 | 
			
		||||
for the specific changes made as a result of their constructive criticism.</p>
 | 
			
		||||
<p>Oct, 1998.  In 1994 Greg Colvin proposed to the C++ Standards Committee
 | 
			
		||||
classes named <strong>auto_ptr</strong> and <strong>counted_ptr</strong> which
 | 
			
		||||
were very similar to what we now call <strong>scoped_ptr</strong> and <strong>shared_ptr</strong>. 
 | 
			
		||||
The committee document was 94-168/N0555, Exception Safe Smart Pointers.  In
 | 
			
		||||
one of the very few cases where the Library Working Group's recommendations were
 | 
			
		||||
not followed by the full committee, <strong>counted_ptr</strong> was rejected
 | 
			
		||||
and surprising transfer-of-ownership semantics were added to <strong>auto-ptr</strong>.</p>
 | 
			
		||||
<p>Beman Dawes proposed reviving the original semantics under the names <strong>safe_ptr</strong>
 | 
			
		||||
and <strong>counted_ptr</strong> at an October, 1998, meeting of Per Andersson,
 | 
			
		||||
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 <strong>std::auto_ptr</strong> interface, and various
 | 
			
		||||
function signatures and semantics were finalized.</p>
 | 
			
		||||
<p>Over the next three months, several implementations were considered for <strong>shared_ptr</strong>,
 | 
			
		||||
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
 | 
			
		||||
-->27 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14992"
 | 
			
		||||
--></p>
 | 
			
		||||
<p><EFBFBD> Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										263
									
								
								smart_ptr_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								smart_ptr_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
			
		||||
//  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
 | 
			
		||||
//  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/smart_ptr.hpp>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
#ifdef NDEBUG
 | 
			
		||||
#error This test program makes no sense if NDEBUG is defined
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
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 ) { assert( *v1 == v2 ); }
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
  int UDT_use_count;  // independent of pointer maintained counts
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
//  user defined type  -------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
class UDT {
 | 
			
		||||
  long value_;
 | 
			
		||||
 public:
 | 
			
		||||
  explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; }
 | 
			
		||||
  ~UDT() {
 | 
			
		||||
    --UDT_use_count;
 | 
			
		||||
    cout << "UDT with value " << value_ << " being destroyed" << endl;
 | 
			
		||||
    }
 | 
			
		||||
  long value() const { return value_; }
 | 
			
		||||
  void value( long v ) { value_ = v;; }
 | 
			
		||||
  };  // UDT
 | 
			
		||||
 | 
			
		||||
//  main  --------------------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  This isn't a very systematic test; it just hits some of the basics.
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
 | 
			
		||||
  assert( UDT_use_count == 0 );  // reality check
 | 
			
		||||
 | 
			
		||||
  //  test scoped_ptr with a built-in type
 | 
			
		||||
  long * lp = new long;
 | 
			
		||||
  scoped_ptr<long> sp ( lp );
 | 
			
		||||
  assert( sp.get() == lp );
 | 
			
		||||
  assert( lp == sp.get() );
 | 
			
		||||
  assert( &*sp == lp );
 | 
			
		||||
 | 
			
		||||
  *sp = 1234568901L;
 | 
			
		||||
  assert( *sp == 1234568901L );
 | 
			
		||||
  assert( *lp == 1234568901L );
 | 
			
		||||
  ck( static_cast<long*>(sp.get()), 1234568901L );
 | 
			
		||||
  ck( lp, *sp );
 | 
			
		||||
 | 
			
		||||
  sp.reset();
 | 
			
		||||
  assert( sp.get() == 0 );
 | 
			
		||||
 | 
			
		||||
  //  test scoped_ptr with a user defined type
 | 
			
		||||
  scoped_ptr<UDT> udt_sp ( new UDT( 999888777 ) );
 | 
			
		||||
  assert( udt_sp->value() == 999888777 );
 | 
			
		||||
  udt_sp.reset();
 | 
			
		||||
  udt_sp.reset( new UDT( 111222333 ) );
 | 
			
		||||
  assert( udt_sp->value() == 111222333 );
 | 
			
		||||
  udt_sp.reset( new UDT( 333222111 ) );
 | 
			
		||||
  assert( udt_sp->value() == 333222111 );
 | 
			
		||||
 | 
			
		||||
  //  test scoped_array with a build-in type
 | 
			
		||||
  char * sap = new char [ 100 ];
 | 
			
		||||
  scoped_array<char> sa ( sap );
 | 
			
		||||
  assert( sa.get() == sap );
 | 
			
		||||
  assert( sap == sa.get() );
 | 
			
		||||
 | 
			
		||||
  strcpy( sa.get(), "Hot Dog with mustard and relish" );
 | 
			
		||||
  assert( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
 | 
			
		||||
  assert( sa[0] == 'H' );
 | 
			
		||||
  assert( sa[30] == 'h' );
 | 
			
		||||
 | 
			
		||||
  sa[0] = 'N';
 | 
			
		||||
  sa[4] = 'd';
 | 
			
		||||
  assert( strcmp( sap, "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
 | 
			
		||||
  sa.reset();
 | 
			
		||||
  assert( sa.get() == 0 );
 | 
			
		||||
 | 
			
		||||
  //  test shared_ptr with a built-in type
 | 
			
		||||
  int * ip = new int;
 | 
			
		||||
  shared_ptr<int> cp ( ip );
 | 
			
		||||
  assert( ip == cp.get() );
 | 
			
		||||
  assert( cp.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  *cp = 54321;
 | 
			
		||||
  assert( *cp == 54321 );
 | 
			
		||||
  assert( *ip == 54321 );
 | 
			
		||||
  ck( static_cast<int*>(cp.get()), 54321 );
 | 
			
		||||
  ck( static_cast<int*>(ip), *cp );
 | 
			
		||||
 | 
			
		||||
  shared_ptr<int> cp2 ( cp );
 | 
			
		||||
  assert( ip == cp2.get() );
 | 
			
		||||
  assert( cp.use_count() == 2 );
 | 
			
		||||
  assert( cp2.use_count() == 2 );
 | 
			
		||||
 | 
			
		||||
  assert( *cp == 54321 );
 | 
			
		||||
  assert( *cp2 == 54321 );
 | 
			
		||||
  ck( static_cast<int*>(cp2.get()), 54321 );
 | 
			
		||||
  ck( static_cast<int*>(ip), *cp2 );
 | 
			
		||||
  
 | 
			
		||||
  shared_ptr<int> cp3 ( cp );
 | 
			
		||||
  assert( cp.use_count() == 3 );
 | 
			
		||||
  assert( cp2.use_count() == 3 );
 | 
			
		||||
  assert( cp3.use_count() == 3 );
 | 
			
		||||
  cp.reset();
 | 
			
		||||
  assert( cp2.use_count() == 2 );
 | 
			
		||||
  assert( cp3.use_count() == 2 );
 | 
			
		||||
  assert( cp.use_count() == 1 );
 | 
			
		||||
  cp.reset( new int );
 | 
			
		||||
  *cp =  98765;
 | 
			
		||||
  assert( *cp == 98765 );
 | 
			
		||||
  *cp3 = 87654;
 | 
			
		||||
  assert( *cp3 == 87654 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  cp.swap( cp3 );
 | 
			
		||||
  assert( *cp == 87654 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  assert( *cp3 == 98765 );
 | 
			
		||||
  cp.swap( cp3 );
 | 
			
		||||
  assert( *cp == 98765 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  assert( *cp3 == 87654 );
 | 
			
		||||
  cp2 = cp2;
 | 
			
		||||
  assert( cp2.use_count() == 2 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  cp = cp2;
 | 
			
		||||
  assert( cp2.use_count() == 3 );
 | 
			
		||||
  assert( *cp2 == 87654 );
 | 
			
		||||
  assert( cp.use_count() == 3 );
 | 
			
		||||
  assert( *cp == 87654 );
 | 
			
		||||
  
 | 
			
		||||
  shared_ptr<int> cp4;
 | 
			
		||||
  swap( cp2, cp4 );
 | 
			
		||||
  assert( cp4.use_count() == 3 );
 | 
			
		||||
  assert( *cp4 == 87654 );
 | 
			
		||||
  assert( cp2.get() == 0 );
 | 
			
		||||
  
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
  set< shared_ptr<int> > scp;
 | 
			
		||||
  scp.insert(cp4);
 | 
			
		||||
  assert( scp.find(cp4) != scp.end() );
 | 
			
		||||
  assert( scp.find(cp4) == scp.find( shared_ptr<int>(cp4) ) );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  //  test shared_array with a built-in type
 | 
			
		||||
  char * cap = new char [ 100 ];
 | 
			
		||||
  shared_array<char> ca ( cap );
 | 
			
		||||
  assert( ca.get() == cap );
 | 
			
		||||
  assert( cap == ca.get() );
 | 
			
		||||
  assert( &ca[0] == cap );
 | 
			
		||||
 | 
			
		||||
  strcpy( ca.get(), "Hot Dog with mustard and relish" );
 | 
			
		||||
  assert( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 );
 | 
			
		||||
 | 
			
		||||
  assert( ca[0] == 'H' );
 | 
			
		||||
  assert( ca[30] == 'h' );
 | 
			
		||||
  
 | 
			
		||||
  shared_array<char> ca2 ( ca );
 | 
			
		||||
  shared_array<char> ca3 ( ca2 );
 | 
			
		||||
 | 
			
		||||
  ca[0] = 'N';
 | 
			
		||||
  ca[4] = 'd';
 | 
			
		||||
  assert( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( ca.use_count() == 3 );
 | 
			
		||||
  assert( ca2.use_count() == 3 );
 | 
			
		||||
  assert( ca3.use_count() == 3 );
 | 
			
		||||
  ca2.reset();
 | 
			
		||||
  assert( ca.use_count() == 2 );
 | 
			
		||||
  assert( ca3.use_count() == 2 );
 | 
			
		||||
  assert( ca2.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  ca.reset();
 | 
			
		||||
  assert( ca.get() == 0 );
 | 
			
		||||
 | 
			
		||||
  shared_array<char> ca4;
 | 
			
		||||
  swap( ca3, ca4 );
 | 
			
		||||
  assert( ca4.use_count() == 1 );
 | 
			
		||||
  assert( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 );
 | 
			
		||||
  assert( ca3.get() == 0 );
 | 
			
		||||
  
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
  set< shared_array<char> > sca;
 | 
			
		||||
  sca.insert(ca4);
 | 
			
		||||
  assert( sca.find(ca4) != sca.end() );
 | 
			
		||||
  assert( sca.find(ca4) == sca.find( shared_array<char>(ca4) ) );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  //  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 );
 | 
			
		||||
 | 
			
		||||
  assert( udta[0].value() == 111 );
 | 
			
		||||
  assert( udta[1].value() == 222 );
 | 
			
		||||
  assert( udta[2].value() == 333 );
 | 
			
		||||
  assert( udta2[0].value() == 111 );
 | 
			
		||||
  assert( udta2[1].value() == 222 );
 | 
			
		||||
  assert( udta2[2].value() == 333 );
 | 
			
		||||
  udta2.reset();
 | 
			
		||||
  assert( udta2.get() == 0 );
 | 
			
		||||
  assert( udta.use_count() == 1 );
 | 
			
		||||
  assert( udta2.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  assert( UDT_use_count == 4 );  // reality check
 | 
			
		||||
 | 
			
		||||
  //  test shared_ptr with a user defined type
 | 
			
		||||
  UDT * up = new UDT;
 | 
			
		||||
  shared_ptr<UDT> sup ( up );
 | 
			
		||||
  assert( up == sup.get() );
 | 
			
		||||
  assert( sup.use_count() == 1 );
 | 
			
		||||
 | 
			
		||||
  sup->value( 54321 ) ;
 | 
			
		||||
  assert( sup->value() == 54321 );
 | 
			
		||||
  assert( up->value() == 54321 );
 | 
			
		||||
 | 
			
		||||
  shared_ptr<UDT> sup2;
 | 
			
		||||
  sup2 = sup;
 | 
			
		||||
  assert( sup2->value() == 54321 );
 | 
			
		||||
  assert( sup.use_count() == 2 );
 | 
			
		||||
  assert( sup2.use_count() == 2 );
 | 
			
		||||
  sup2 = sup2;
 | 
			
		||||
  assert( sup2->value() == 54321 );
 | 
			
		||||
  assert( sup.use_count() == 2 );
 | 
			
		||||
  assert( sup2.use_count() == 2 );
 | 
			
		||||
 | 
			
		||||
  cout << "OK" << endl;
 | 
			
		||||
 | 
			
		||||
  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.
										
									
								
							
							
								
								
									
										540
									
								
								smarttests.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										540
									
								
								smarttests.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,540 @@
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<title>boost: smart pointer tests</title>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
<!--
 | 
			
		||||
-->
 | 
			
		||||
<body bgcolor="#FFFFFF">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Smart
 | 
			
		||||
Pointers Timings </h1>
 | 
			
		||||
 | 
			
		||||
<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"></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"></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 -->27 Jul 2000<!--webbot bot="Timestamp" endspan i-checksum="14992" -->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
 | 
			
		||||
and distribute this document is granted provided this copyright notice appears in all
 | 
			
		||||
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