From d3347b6d0832eec766fb70731e9aeb07f31450b0 Mon Sep 17 00:00:00 2001 From: Beman Dawes Date: Thu, 27 Jul 2000 14:27:00 +0000 Subject: [PATCH] Initial HTML commit [SVN r7640] --- index.htm | 37 ++++ scoped_array.htm | 90 ++++++++ scoped_ptr.htm | 128 +++++++++++ shared_array.htm | 180 ++++++++++++++++ shared_ptr.htm | 206 ++++++++++++++++++ smart_ptr.htm | 138 ++++++++++++ smarttests.htm | 540 +++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1319 insertions(+) create mode 100644 index.htm create mode 100644 scoped_array.htm create mode 100644 scoped_ptr.htm create mode 100644 shared_array.htm create mode 100644 shared_ptr.htm create mode 100644 smart_ptr.htm create mode 100644 smarttests.htm diff --git a/index.htm b/index.htm new file mode 100644 index 0000000..04643fa --- /dev/null +++ b/index.htm @@ -0,0 +1,37 @@ + + + + +Boost Smart Pointer Library + + + + + + + + + + + + + + +
c++boost.gif (8819 bytes)Home Libraries People FAQ More
+ +

Smart pointer library

+ +

The header smart_ptr.h provides four smart pointer classes.  Smart pointers ease +the management of memory dynamically allocated with C++ new expressions. + +

+ +

Revised July 23, 1999

+ + diff --git a/scoped_array.htm b/scoped_array.htm new file mode 100644 index 0000000..3bf65cd --- /dev/null +++ b/scoped_array.htm @@ -0,0 +1,90 @@ + + + +scoped_array + + + + + + +

c++boost.gif (8819 bytes)Class +scoped_array

+

Class scoped_array stores a pointer to a dynamically +allocated array. (Dynamically allocated arrays are allocated with the C++ new[] +expression.)   The array pointed to is guaranteed to be deleted, +either on destruction of the scoped_array, or via an explicit scoped_array::reset().

+

Class scoped_array is a simple solution for simple +needs.  It cannot be used in C++ Standard Library containers.  See shared_array +if scoped_array does not meet your needs.

+

Class scoped_array cannot correctly hold a pointer to a +single object.  See scoped_ptr +for that usage.

+

Because scoped_array 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.

+

A heavier duty alternative to a scoped_array is a scoped_ptr +to a C++ Standard Library vector.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer common +requirements.

+

Class scoped_array Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class scoped_array : noncopyable {
+
+ public:
+   typedef T element_type;
+
+   explicit scoped_array( T* p=0 );  // never throws
+   ~scoped_array();
+
+   void reset( T* p=0 );
+
+   T& operator[](std::size_t i) const;  // never throws
+   T* get() const;  // never throws
+   };
+}
+

Class scoped_array Members

+

scoped_array element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

scoped_array constructors

+
explicit scoped_array( T* p=0 );  // never throws
+

Constructs a scoped_array, storing a copy of p, which must +have been allocated via a C++ new[] expression or be 0.

+

scoped_array destructor

+
~scoped_array();
+

Deletes the array pointed to by the stored pointer.  Note that in C++ delete[] +on a pointer with a value of 0 is harmless.

+

Does not throw exceptions.

+

scoped_array reset

+
void reset( T* p=0 )();
+

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++ new[] expression or be 0.

+

Does not throw exceptions.

+

scoped_array operator[]

+

T& operator[](std::size_t i) const; // never throws

+

Returns a reference to element i of the array pointed to by the +stored pointer.

+

Behavior is undefined (and almost certainly undesirable) if get()==0, +or if i is less than 0 or is greater or equal to the number of elements +in the array.

+

scoped_array get

+
T* get() const;  // never throws
+

Returns the stored pointer.

+

Class scoped_array example

+

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

+
+

Revised  December 8, 1999

+

© 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.

+ + + + diff --git a/scoped_ptr.htm b/scoped_ptr.htm new file mode 100644 index 0000000..3430481 --- /dev/null +++ b/scoped_ptr.htm @@ -0,0 +1,128 @@ + + + +scoped_ptr + + + + + + +

c++boost.gif (8819 bytes)Class +scoped_ptr

+

Class scoped_ptr stores a pointer to a dynamically allocated +object. (Dynamically allocated objects are allocated with the C++ new +expression.)   The object pointed to is guaranteed to be deleted, +either on destruction of the scoped_ptr, or via an explicit scoped_ptr::reset().  +See example.

+

Class scoped_ptr is a simple solution for simple +needs.  It cannot be used in C++ Standard Library containers.  See shared_ptr +or std::auto_ptr if scoped_ptr does not meet your needs.

+

Class scoped_ptr cannot correctly hold a pointer to a +dynamically allocated array.  See scoped_array +for that usage.

+

Because scoped_ptr 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.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer common +requirements.

+

Class scoped_ptr Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class scoped_ptr : noncopyable {
+
+ public:
+   typedef T element_type;
+
+   explicit scoped_ptr( T* p=0 );  // never throws
+   ~scoped_ptr();
+
+   void reset( T* p=0 );
+
+   T& operator*() const;  // never throws
+   T* operator->() const;  // never throws
+   T* get() const;  // never throws
+   };
+}
+

Class scoped_ptr Members

+

scoped_ptr element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

scoped_ptr constructors

+
explicit scoped_ptr( T* p=0 );  // never throws
+

Constructs a scoped_ptr, storing a copy of p, which must +have been allocated via a C++ new expression or be 0..

+

scoped_ptr destructor

+
~scoped_ptr();
+

Deletes the object pointed to by the stored pointer.  Note that in C++, delete +on a pointer with a value of 0 is harmless.

+

Does not throw exceptions.

+

scoped_ptr reset

+
void reset( T* p=0 );
+

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++ new expression or be 0.

+

Does not throw exceptions.

+

scoped_ptr operator*

+
T& operator*() const;  // never throws
+

Returns a reference to the object pointed to by the stored pointer.

+

scoped_ptr operator-> and get

+
T* operator->() const;  // never throws
+T* get() const;  // never throws
+

Both return the stored pointer.

+

Class scoped_ptr examples

+
#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;
+    }
+

The example program produces the beginning of a child's nursery rhyme as +output:

+
+
1
+2
+Buckle my shoe
+
+

Handle/Body Idiom

+

One common usage of shared_pointer is to implement a handle/body +structure which avoids exposing the body (implementation) in the header file:

+
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;
+};
+

This code requires that class body have a trivial destructor to +avoid undefined behavior.  This is because the definition of class +body 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.

+
+

Revised 24 July 2000

+

© 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.

+ + + + diff --git a/shared_array.htm b/shared_array.htm new file mode 100644 index 0000000..eebafdc --- /dev/null +++ b/shared_array.htm @@ -0,0 +1,180 @@ + + + +shared_array + + + + + + +

c++boost.gif (8819 bytes)Class +shared_array

+

Class shared_array stores a pointer to a dynamically +allocated array. (Dynamically allocated arrays are allocated with the C++ new[] +expression.)   The array pointed to is guaranteed to be deleted, +either on destruction of the shared_array, on shared_array::operator=(), +or via an explicit shared_array::reset().  See example.

+

Class shared_array meets the CopyConstuctible +and Assignable 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  +shared_array 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.

+

Class shared_array cannot correctly hold a pointer to a +single object.  See shared_array +for that usage.

+

Class shared_array 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.

+

A heavier duty alternative to a shared_array is a shared_ptr +to a C++ Standard Library vector.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer Common +requirements.

+

Class shared_array Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class shared_array {
+
+ public:
+   typedef T element_type;
+
+   explicit shared_array( T* p=0 );
+   shared_array( const shared_array& );  // never throws   
+   ~shared_array();
+
+   shared_array& operator=( const shared_array& );  // never throws  
+
+   void reset( T* p=0 );
+
+   T& operator[](std::size_t i) const;  // never throws
+   T* get() const;  // never throws
+
+   long use_count() const;  // never throws
+   bool unique() const;  // never throws
+
+   void swap( 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(); }
+}
+
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 
+

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.
+
+Specialization of std::less allows use of shared arrays as keys in C++ +Standard Library associative collections.
+
+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).
+
+It's still a controversial question whether supplying only std::less is better +than supplying a full range of comparison operators (<, >, <=, >=).

+

The current implementation does not supply the specializations if the macro +name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

+

Class shared_array Members

+

shared_array element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

shared_array constructors

+
explicit shared_array( T* p=0 );
+

Constructs a shared_array, storing a copy of p, +which must have been allocated via a C++ new[] expression or be 0. +Afterwards, use_count() is 1 (even if p==0; see ~shared_array).

+

The only exception which may be thrown is std::bad_alloc.  If +an exception is thrown,  delete[] p is called.

+
shared_array( const shared_array& r);  // never throws
+

Constructs a shared_array, as if by storing a copy of the +pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count().

+

shared_array destructor

+
~shared_array();
+

If use_count() == 1, deletes the array pointed to by the +stored pointer. Otherwise, use_count() for any remaining +copies is decremented by 1. Note that in C++ delete[] on a pointer with +a value of 0 is harmless.

+

Does not throw exceptions.

+

shared_array operator=

+
shared_array& operator=( const shared_array& r);  // never throws
+

First, if use_count() == 1, deletes the array pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. Note that in C++ delete[] on a +pointer with a value of 0 is harmless.

+

Then replaces the contents of this, as if by storing a copy +of the pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count()

+

shared_array reset

+
void reset( T* p=0 );
+

First, if use_count() == 1, deletes the array pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. Note that in C++  delete[] +on a pointer with a value of 0 is harmless.

+

Then replaces the contents of this, as if by storing a copy +of p, which must have been allocated via a C++ new[] +expression or be 0. Afterwards, use_count() is 1 (even if p==0; +see ~shared_array).

+

The only exception which may be thrown is std::bad_alloc.  If +an exception is thrown,  delete[] p is called.

+

shared_array operator[]

+

T& operator[](std::size_t i) const; // never throws

+

Returns a reference to element i of the array pointed to by the +stored pointer.

+

Behavior is undefined (and almost certainly undesirable) if get()==0, +or if i is less than 0 or is greater or equal to the number of elements +in the array.

+

shared_array get

+
T* get() const;  // never throws
+

Returns the stored pointer.

+

shared_array use_count

+

long use_count() const; // never throws

+

Returns the number of shared_arrays sharing ownership of the +stored pointer.

+

shared_array unique

+

bool unique() const; // never throws

+

Returns use_count() == 1.

+

shared_array swap

+

void swap( shared_array<T>& other ) throw()

+

Swaps the two smart pointers, as if by std::swap.

+

Class shared_array example

+

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

+
+

Revised December 8, 1999

+

© 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.

+ + + + diff --git a/shared_ptr.htm b/shared_ptr.htm new file mode 100644 index 0000000..3fdca13 --- /dev/null +++ b/shared_ptr.htm @@ -0,0 +1,206 @@ + + + +shared_ptr + + + + + + +

c++boost.gif (8819 bytes)Class +shared_ptr

+

Class shared_ptr stores a pointer to a dynamically allocated +object. (Dynamically allocated objects are allocated with the C++ new +expression.)   The object pointed to is guaranteed to be deleted when +the last shared_ptr pointing to it is deleted or reset.  +See example.

+

Class shared_ptr meets the CopyConstuctible +and Assignable 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  +shared_ptr 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.

+

Class shared_ptr cannot correctly hold a pointer to a +dynamically allocated array.  See shared_array +for that usage.

+

Class shared_ptr 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.

+

The class is a template parameterized on T, the type of the object +pointed to.   T must meet the smart pointer Common +requirements.

+

Class shared_ptr Synopsis

+
#include <boost/smart_ptr.hpp>
+namespace boost {
+
+template<typename T> class shared_ptr {
+
+ public:
+   typedef T element_type;
+
+   explicit shared_ptr( T* p=0 );
+   ~shared_ptr();
+
+   shared_ptr( const shared_ptr& );   
+   template<typename Y>
+      shared_ptr(const shared_ptr<Y>& r);  // never throws
+   template<typename Y>
+      shared_ptr(std::auto_ptr<Y>& r);
+
+   shared_ptr& operator=( const shared_ptr& );  // never throws  
+   template<typename Y>
+      shared_ptr& operator=(const shared_ptr<Y>& r);  // never throws
+   template<typename Y>
+      shared_ptr& operator=(std::auto_ptr<Y>& r);
+
+   void reset( T* p=0 );
+
+   T& operator*() const;  // never throws
+   T* operator->() const;  // never throws
+   T* get() const;  // never throws
+
+   long use_count() const;  // never throws
+   bool unique() const;  // never throws
+
+   void swap( 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(); }
+}
+
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 
+

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.
+
+Specialization of std::less allows use of shared pointers as keys in C++ +Standard Library associative collections.
+
+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).
+
+It's still a controversial question whether supplying only std::less is better +than supplying a full range of comparison operators (<, >, <=, >=).

+

The current implementation does not supply the specializations if the macro +name BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION is defined.

+

The current implementation does not supply the member template functions if +the macro name BOOST_NO_MEMBER_TEMPLATES is defined.

+

Class shared_ptr Members

+

shared_ptr element_type

+
typedef T element_type;
+

Provides the type of the stored pointer.

+

shared_ptr constructors

+
explicit shared_ptr( T* p=0 );
+

Constructs a shared_ptr, storing a copy of p, which +must have been allocated via a C++ new expression or be 0. Afterwards, use_count() +is 1 (even if p==0; see ~shared_ptr).

+

The only exception which may be thrown by this constructor is std::bad_alloc.   +If an exception is thrown,  delete p is called.

+
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);
+

Constructs a shared_ptr, as if by storing a copy of the +pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count(), or 1 +in the auto_ptr case. In the auto_ptr case, r.release() +is called.

+

The only exception which may be thrown by the constructor from auto_ptr +is std::bad_alloc.   If an exception is thrown, that +constructor has no effect.

+

shared_ptr destructor

+
~shared_ptr();
+

If use_count() == 1, deletes the object pointed to by the +stored pointer. Otherwise, use_count() for any remaining +copies is decremented by 1. Note that in C++  delete on a pointer +with a value of 0 is harmless.

+

Does not throw exceptions.

+

shared_ptr operator=

+
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);
+

First, if use_count() == 1, deletes the object pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. Note that in C++  delete on +a pointer with a value of 0 is harmless.

+

Then replaces the contents of this, as if by storing a copy +of the pointer stored in r. Afterwards, use_count() +for all copies is 1 more than the initial r.use_count(), or 1 +in the auto_ptr case. In the auto_ptr case, r.release() +is called.

+

The first two forms of operator= above do not throw exceptions.

+

The only exception which may be thrown by the auto_ptr form +is std::bad_alloc.   If an exception is thrown, the function +has no effect.

+

shared_ptr reset

+
void reset( T* p=0 );
+

First, if use_count() == 1, deletes the object pointed to by +the stored pointer. Otherwise, use_count() for any +remaining copies is decremented by 1. 

+

Then replaces the contents of this, as if by storing a copy +of p, which must have been allocated via a C++ new +expression or be 0. Afterwards, use_count() is 1 (even if p==0; +see ~shared_ptr). Note that in C++  delete +on a pointer with a value of 0 is harmless.

+

The only exception which may be thrown is std::bad_alloc.  If +an exception is thrown,  delete p is called.

+

shared_ptr operator*

+
T& operator*() const;  // never throws
+

Returns a reference to the object pointed to by the stored pointer.

+

shared_ptr operator-> and get

+
T* operator->() const;  // never throws
+T* get() const;  // never throws
+

Both return the stored pointer.

+

shared_ptr use_count

+

long use_count() const; // never throws

+

Returns the number of shared_ptrs sharing ownership of the +stored pointer.

+

shared_ptr unique

+

bool unique() const; // never throws

+

Returns use_count() == 1.

+

shared_ptr swap

+

void swap( shared_ptr<T>& other ) throw()

+

Swaps the two smart pointers, as if by std::swap.

+

Class shared_ptr example

+

[To be supplied. In the meantime, see smart_ptr_test.cpp.]

+
+

Revised December 8, 1999

+

© 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.

+ + + + diff --git a/smart_ptr.htm b/smart_ptr.htm new file mode 100644 index 0000000..ab95fc8 --- /dev/null +++ b/smart_ptr.htm @@ -0,0 +1,138 @@ + + + + + + +Smart Pointer Classes + + + + +

c++boost.gif (8819 bytes)Smart +Pointers

+

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.

+

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.

+

The header boost/smart_ptr.hpp +provides four smart pointer template classes:

+
+ + + + + + + + + + + + + + + + + +
+

scoped_ptr

Simple sole ownership of single objects.
scoped_arraySimple sole ownership of arrays.
shared_ptrObject ownership shared among multiple pointers
shared_arrayArray ownership shared among multiple pointers.
+
+

These classes are designed to complement the C++ Standard Library auto_ptr +class.

+

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.

+

A test program (smart_ptr_test.cpp) is +provided to verify correct operation.

+

A page on Smart Pointer Timings will be of +interest to those curious about performance issues.

+

Common requirements

+

These smart pointer classes have a template parameter, T, 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 T throws exceptions.

+

Exception safety

+

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 T meets the Common +requirements)  is std::bad_alloc, and that is thrown only by +functions which are explicitly documented as possibly throwing std::bad_alloc.

+

Exception-specifications

+

Exception-specifications are not used; see exception-specification +rationale.

+

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: // +never throws.

+

Functions which destroy objects of the pointed to type are prohibited from +throwing exceptions by the Common requirements.

+

History and acknowledgements

+

November, 1999. Darin Adler provided operator ==, operator !=, and std::swap +and std::less specializations for shared types.

+

September, 1999. Luis Coelho provided shared_ptr::swap and shared_array::swap

+

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 smart_ptr.hpp +for the specific changes made as a result of their constructive criticism.

+

Oct, 1998.  In 1994 Greg Colvin proposed to the C++ Standards Committee +classes named auto_ptr and counted_ptr which +were very similar to what we now call scoped_ptr and shared_ptr.  +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, counted_ptr was rejected +and surprising transfer-of-ownership semantics were added to auto-ptr.

+

Beman Dawes proposed reviving the original semantics under the names safe_ptr +and counted_ptr at an October, 1998, meeting of Per Andersson, +Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar +Kü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 std::auto_ptr interface, and various +function signatures and semantics were finalized.

+

Over the next three months, several implementations were considered for shared_ptr, +and discussed on the boost.org 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: +

+

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.

+

But Greg Colvin and Jerry Schwarz argued that "parameterization will +discourage users", and in the end we choose to supply only the direct +implementation.

+

See the Revision History section of the header for further contributors.

+
+

Revised  24 Jul 2000

+

© 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.

+ + + + diff --git a/smarttests.htm b/smarttests.htm new file mode 100644 index 0000000..dd976e4 --- /dev/null +++ b/smarttests.htm @@ -0,0 +1,540 @@ + + +boost: smart pointer tests + + + + +

c++boost.gif (8819 bytes)Smart +Pointers Timings

+ +

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.

+

Thanks are due to Dave Abrahams, + Gavin Collings, Greg Colvin and + Beman Dawes + for test code and trial implementations, the final version of which can be found + in .zip format here.

+

Description

+

Two tests were run: the first aimed to obtain timings for two basic individual + operations:

+
    +
  1. Initial construction from raw pointer.
  2. +
  3. An amortized copy operation consisting of half an assignment and half a + copy construction - designed to reflect average usage.
  4. +
+

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.

+

Five smart pointer implementation strategies were tested:

+
    +
  1. Counted pointer using a heap allocated reference count, this is referred + to as simple counted.
  2. +
  3. Counted pointer using a special purpose allocator for the reference count + - special counted.
  4. +
  5. Counted pointer using an intrusive reference count - intrusive.
  6. +
  7. Linked pointer as described above - linked.
  8. +
  9. Cyclic pointer, a counted implementation using a std::deque for allocation + with provision for weak pointers and garbage collection of cycles of pointers + - cyclic.
  10. +
+

on two compilers:

+
    +
  1. 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).
  2. +
  3. gcc 2.95.2 using full optimization (-O3 -DNDEBUG).
  4. +
+

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.

+

All tests were run on a PII-200 running Windows NT version 4.0

+

 

+

Operation Timing Test Results

+

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.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
   
   
   
  
   
+

 

+

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) : -

+

 

+

MSVC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
initialization
+
copy operation
+
simple counted
+
3000 +/- 170104 +/- 31
+
special counted
+
1330 +/- 5085 +/- 9
+
intrusive
+
1000 +/- 2071 +/- 3
linked970 +/- 60136 +/- 10
cyclic1290 +/- 70112 +/- 12
dumb1020 +/- 2010 +/- 4
+
raw
+
1038 +/- 3010 +/- 5
+

 

+

GCC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
initialization
+
copy operation
+
simple counted
+
4620 +/- 150301 +/- 28
+
special counted
+
1990 +/- 40264 +/- 7
+
intrusive
+
1590 +/- 70181 +/- 12
linked1470 +/- 140345 +/- 26
cyclic2180 +/- 100330 +/- 18
dumb1590 +/- 7074 +/- 12
+
raw
+
1430 +/- 6027 +/- 11
+

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.

+

Detail

+

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.

+

 

+

Container Test Results

+

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.

+

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.

+

All times are in seconds for 300,000 contained pointers.

+

GCC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 vectorlist
+
+
+
fill
+
sortfillsort
+
simple counted
+
46.542.4447.093.22
+
special counted
+
14.022.837.283.21
+
intrusive
+
12.151.917.993.08
linked12.462.328.143.27
cyclic22.603.191.633.18
+
raw
+
11.810.2427.510.77
+

 

+

MSVC

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 vectorlist
+
+
+
fill
+
sortfillsort
+
simple counted
+
1.832.371.864.85
+
special counted
+
1.042.351.384.58
+
intrusive
+
1.041.841.164.29
linked1.082.001.214.33
cyclic1.382.841.474.73
+
raw
+
0.670.281.241.81
+

 

+

Code Size

+

The following code sizes were determined by inspection of generated code for + MSVC only. Sizes are given in the form N / M / I where:

+ +

 

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
ptr()
+
ptr(p)ptr(ptr)op=() +
~ptr()
+
+
simple counted
+
38/110/O38/110/O9/23/I22/57/I17/40/I
+
special counted
+
50/141/O50/141/O9/23/I23/64/I13/38/I
+
intrusive
+
1/2/I3/6/I3/6/I6/11/I6/11/I
+
linked
+
5/19/I5/15/I10/30/I27/59/I14/38/I
+

During the code inspection, a couple of minor points were noticed: -

+ +

 

+

Data Size

+

The following smart pointer sizes were obtained in bytes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
MSVC
+
+
GCC
+
+
simple counted
+
+
8
+
+
8
+
+
special counted
+
+
8
+
+
12
+
+
intrusive
+
+
4
+
+
4
+
+
linked
+
+
12
+
+
12
+
+
cyclic
+
+
8
+
+
8
+
+

 

+

Summary

+

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: -

+ +
+

Revised 21 Feb 2000 +

+

© 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.

+ +