diff --git a/compatibility.htm b/compatibility.htm new file mode 100644 index 0000000..65acfd7 --- /dev/null +++ b/compatibility.htm @@ -0,0 +1,105 @@ + + + + +
+ +The February 2002 change to the Boost smart pointers introduced a number +of changes. Since the previous version of the smart pointers was in use for +a long time, it's useful to have a detailed list of what changed from a library +user's point of view.
+ +Note that for compilers that don't support member templates well enough, +a separate implementation is used that lacks many of the new features and is +more like the old version.
+ +Revised 1 February 2002
+ +Copyright 2002 Darin Adler. +Permission to copy, use, +modify, sell and distribute this document is granted provided this copyright +notice appears in all copies. This document is provided "as is" +without express or implied warranty, and with no claim as to its suitability for +any purpose.
+ + + + diff --git a/include/boost/scoped_array.hpp b/include/boost/scoped_array.hpp index 3fcce8d..74ecebe 100644 --- a/include/boost/scoped_array.hpp +++ b/include/boost/scoped_array.hpp @@ -35,49 +35,49 @@ public: typedef T element_type; - explicit scoped_array( T* p = 0 ): ptr(p) // never throws + explicit scoped_array(T * p = 0) : ptr(p) // never throws { } - ~scoped_array() + ~scoped_array() // never throws { typedef char type_must_be_complete[sizeof(T)]; delete [] ptr; } - void reset( T* p = 0 ) + void reset(T * p = 0) // never throws { typedef char type_must_be_complete[sizeof(T)]; - if ( ptr != p ) + if (ptr != p) { delete [] ptr; ptr = p; } } - T& operator[](std::ptrdiff_t i) const // never throws + T& operator[](std::ptrdiff_t i) const // never throws { BOOST_ASSERT(ptr != 0); BOOST_ASSERT(i >= 0); return ptr[i]; } - T* get() const // never throws + T* get() const // never throws { return ptr; } - void swap(scoped_array & rhs) + void swap(scoped_array & b) // never throws { - T * tmp = rhs.ptr; - rhs.ptr = ptr; + T * tmp = b.ptr; + b.ptr = ptr; ptr = tmp; } }; -templateThe header smart_ptr.hpp provides four smart pointer classes. Smart -pointers ease the management of memory dynamically allocated with C++ new -expressions. +
The smart pointer library includes five smart pointer class templates. Smart +pointers ease the management of memory dynamically allocated with C++ new +expressions. In addition, scoped_ptr can ease the management of memory +dynamically allocated in other ways.
Revised 14 Mar 2001 -
+ +Revised 1 February 2002.
diff --git a/scoped_array.htm b/scoped_array.htm index 518b4cb..4df98a9 100644 --- a/scoped_array.htm +++ b/scoped_array.htm @@ -1,101 +1,144 @@ + + +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 supplies a basic "resource acquisition is +
The scoped_array class template 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 reset.
+ +The scoped_array template is a simple solution for simple +needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership -semantics. Both its name and enforcement of semantics (by being noncopyable) -signal its intent to retain ownership solely within the current scope. By -being noncopyable, it is +semantics. Both its name and enforcement of semantics (by being +noncopyable) +signal its intent to retain ownership solely within the current scope. +Because it is noncopyable, it is safer than shared_array for pointers which should not be copied.
-Because scoped_array is so simple, in its usual -implementation every operation is as fast as a built-in array pointer and it has no + +
Because scoped_array is so simple, in its usual implementation +every operation is as fast as a built-in array pointer and it has no more space overhead that a built-in array pointer.
-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 + +
It cannot be used in C++ standard library containers. +See shared_array +if scoped_array does not meet your needs.
+ +It cannot correctly hold a pointer to a single object. +See scoped_ptr for that usage.
-A C++ Standard Library vector is a heavier duty alternative to a scoped_array.
-The class is a template parameterized on T, the type of the object -pointed to. T must meet the smart pointer common -requirements.
-#include <boost/smart_ptr.hpp> -namespace boost { -template<typename T> class scoped_array : noncopyable { +A std::vector is an alternative to a scoped_array that is +a bit heavier duty but far more flexible. +A boost::array is an alternative that does not use dynamic allocation.
- public: - typedef T element_type; +The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.
- explicit scoped_array( T* p=0 ); // never throws - ~scoped_array(); +Synopsis
- void reset( T* p=0 ); +namespace boost { + + template<typename T> class scoped_array : noncopyable { + + public: + typedef T element_type; + + explicit scoped_array(T * p = 0); // never throws + ~scoped_array(); // never throws + + void reset(T * p = 0); // never throws + + T & operator[](std::size_t i) const; // never throws + T * get() const; // never throws + + void swap(scoped_array & b); // never throws + }; + + template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws - T& operator[](std::size_t i) const; // never throws - T* get() const; // never throws - }; }-Class scoped_array Members
-scoped_array element_type
+ +Members
+ ++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.
-T is not required be a complete type. -See Common Requirements.
-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 )();+ +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. +T is not required be a complete type. +See the smart pointer +common requirements.
+ +destructor
+~scoped_array(); // never throws+Deletes the array pointed to by the stored pointer. +Note that delete[] on a pointer with a value of 0 is harmless. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted array's objects' destructors do not throw exceptions. +See the smart pointer common requirements.
+ +reset
+void reset(T * p = 0); // never throwsIf 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 +C++ new[] expression or be 0. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted array's objects' destructors do not throw exceptions. +See the smart pointer common requirements.
+ +subscripting
+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 the stored pointer is 0, +or if i is less than 0 or is greater than or equal to the number of elements in the array.
-scoped_array get
-T* get() const; // never throws-T is not required be a complete type. -See Common Requirements.
-Returns the stored pointer.
-Class scoped_array example
-[To be supplied. In the meantime, see smart_ptr_test.cpp.]
+ +get
+T * get() const; // never throws+Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.
+ +swap
+void swap(scoped_array & b); // never throws+Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.
+ +Free Functions
+ +swap
+template<typename T> void swap(scoped_array<T> & a, scoped_array<T> & b); // never throws+Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.
+
-Revised 24 May, 2001 -
-© 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.
+ +Revised 1 February 2002
+ +Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +Permission to copy, use, modify, sell and distribute this document is granted +provided this copyright notice appears in all copies. +This document is provided "as is" without express or implied warranty, +and with no claim as to its suitability for any purpose.
diff --git a/scoped_ptr.htm b/scoped_ptr.htm index 652d1bb..ec0057d 100644 --- a/scoped_ptr.htm +++ b/scoped_ptr.htm @@ -1,152 +1,216 @@ + + +scoped_ptr - - --
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 supplies a basic "resource acquisition is +
+ +
scoped_ptr class template
The scoped_ptr class template 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 reset. +See the example.
+ +The scoped_ptr template is a simple solution for simple +needs. It supplies a basic "resource acquisition is initialization" facility, without shared-ownership or transfer-of-ownership -semantics. Both its name and enforcement of semantics (by being noncopyable) -signal its intent to retain ownership solely within the current scope. +semantics. Both its name and enforcement of semantics (by being +noncopyable) +signal its intent to retain ownership solely within the current scope. Because it is noncopyable, it is -safer than shared_ptr or std::auto_ptr for pointers which should not be +safer than shared_ptr or std::auto_ptr for pointers which should not be copied.
-Because scoped_ptr is so simple, in its usual implementation + +
Because scoped_ptr is simple, in its usual implementation every operation is as fast as for a built-in pointer and it has no more space overhead -that a built-in pointer. (Because of the "complete type" -requirement for delete and reset members, they may have one additional function -call overhead in certain idioms. See Handle/Body -Idiom.)
-Class scoped_ptr 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 +that a built-in pointer.
+ +It cannot be used in C++ Standard Library containers. +See shared_ptr +or std::auto_ptr if scoped_ptr does not meet your needs.
+ +It cannot correctly hold a pointer to a +dynamically allocated array. See scoped_array for that usage.
-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 { +The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.
- public: - typedef T element_type; +Synopsis
- explicit scoped_ptr( T* p=0 ); // never throws - ~scoped_ptr(); +namespace boost { - void reset( T* p=0 ); + template<typename T> class scoped_ptr : noncopyable { + + public: + typedef T element_type; + + explicit scoped_ptr(T * p = 0); // never throws + ~scoped_ptr(); // never throws + + void reset(T * p = 0); // never throws + + T & operator*() const; // never throws + T * operator->() const; // never throws + T * get() const; // never throws + + void swap(scoped_ptr & b); // never throws + }; + + template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws - T& operator*() const; // never throws - T* operator->() const; // never throws - T* get() const; // never throws - }; }-Class scoped_ptr Members
-scoped_ptr element_type
+ +Members
+ +element_type
typedef T element_type;Provides the type of the stored pointer.
-scoped_ptr constructors
-explicit scoped_ptr( T* p=0 ); // never throws-T is not required be a complete type. -See Common Requirements.
-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 );+ +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. +T is not required be a complete type. +See the smart pointer +common requirements.
+ +destructor
+~scoped_ptr(); // never throws+Deletes the object pointed to by the stored pointer. +Note that delete on a pointer with a value of 0 is harmless. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements.
+ +reset
+void reset(T * p = 0); // never throwsIf 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-T is not required by get() be a complete type. See Common Requirements.
-Both return the stored pointer.
-Class scoped_ptr examples
-#include <iostream> -#include <boost/smart_ptr.h> +C++ new expression or be 0. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements. -struct Shoe { ~Shoe(){ std::cout << "Buckle my shoe" << std::endl; } }; ++ + +indirection
+T & operator*() const; // never throws+Returns a reference to the object pointed to by the stored pointer. +Behavior is undefined if the stored pointer is 0.
+T * operator->() const; // never throws+Returns the stored pointer. Behavior is undefined if the stored pointer is 0.
+ +get
+T * get() const; // never throws+Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.
+ +swap
+void swap(scoped_ptr & b); // never throws+Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.
+ +Free Functions
+ +swap
+template<typename T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws+Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.
+ +Example
+ +Here's an example that uses scoped_ptr.
+ ++#include <boost/scoped_ptr.hpp> +#include <iostream> + +struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } }; class MyClass { boost::scoped_ptr<int> ptr; public: MyClass() : ptr(new int) { *ptr = 0; } int add_one() { return ++*ptr; } - }; +}; -void main() { +void main() +{ boost::scoped_ptr<Shoe> x(new Shoe); MyClass my_instance; - std::cout << my_instance.add_one() << std::endl; - std::cout << my_instance.add_one() << std::endl; - }-The example program produces the beginning of a child's nursery rhyme as -output:
+ std::cout << my_instance.add_one() << '\n'; + std::cout << my_instance.add_one() << '\n'; +}The example program produces the beginning of a child's nursery rhyme:
++1 2 Buckle my shoeRationale
-The primary reason to use scoped_ptr rather than auto_ptr is to let readers -of your code know that you intend "resource acquisition is initialization" to be applied only for the current scope, and have no intent to transfer -ownership.
-A secondary reason to use scoped_ptr is to prevent a later maintenance programmer from adding a function that actually transfers -ownership by returning the auto_ptr (because the maintenance programmer saw -auto_ptr, and assumed ownership could safely be transferred.)
-Think of bool vs int. We all know that under the covers bool is usually -just an int. Indeed, some argued against including bool in the -C++ standard because of that. But by coding bool rather than int, you tell your readers -what your intent is. Same with scoped_ptr - you are signaling intent.
-It has been suggested that boost::scoped_ptr<T> is equivalent to -std::auto_ptr<T> const. Ed Brey pointed out, however, that -reset() will not work on a std::auto_ptr<T> const.
+ +The primary reason to use scoped_ptr rather than auto_ptr is to let readers +of your code know that you intend "resource acquisition is initialization" to be applied only +for the current scope, and have no intent to transfer ownership.
+ +A secondary reason to use scoped_ptr is to prevent a later maintenance programmer +from adding a function that transfers ownership by returning the auto_ptr, +because the maintenance programmer saw auto_ptr, and assumed ownership could safely +be transferred.
+ +Think of bool vs int. We all know that under the covers bool is usually +just an int. Indeed, some argued against including bool in the +C++ standard because of that. But by coding bool rather than int, you tell your readers +what your intent is. Same with scoped_ptr; by using it you are signaling intent.
+ +It has been suggested that scoped_ptr<T> is equivalent to +std::auto_ptr<T> const. Ed Brey pointed out, however, that +reset will not work on a std::auto_ptr<T> const.
+Handle/Body Idiom
+One common usage of scoped_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.
+The scoped_ptr_example_test.cpp sample program includes a header file, scoped_ptr_example.hpp, which uses a scoped_ptr<> to an incomplete type to hide the -implementation. The -instantiation of member functions which require a complete type occurs in the scoped_ptr_example.cpp +implementation. The +instantiation of member functions which require a complete type occurs in +the scoped_ptr_example.cpp implementation file.
-FAQ
+ +Frequently Asked Questions
+Q. Why doesn't scoped_ptr have a release() member?
+
-A. Because the whole point of scoped_ptr is to signal intent not -to transfer ownership. Use std::auto_ptr if ownership transfer is +A. Because the point of scoped_ptr is to signal intent, not +to transfer ownership. Use std::auto_ptr if ownership transfer is required.
-Revised 24 May 2001
-© 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.
+ +Revised 1 February 2002
+ +Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +Permission to copy, use, modify, sell and distribute this document is granted +provided this copyright notice appears in all copies. +This document is provided "as is" without express or implied warranty, +and with no claim as to its suitability for any purpose.
diff --git a/scoped_ptr_example.hpp b/scoped_ptr_example.hpp index 97c8bff..ae1fb8d 100644 --- a/scoped_ptr_example.hpp +++ b/scoped_ptr_example.hpp @@ -1,6 +1,6 @@ // Boost scoped_ptr_example header file ------------------------------------// -#include+#include // The point of this example is to prove that even though // example::implementation is an incomplete type in translation units using diff --git a/shared_array.htm b/shared_array.htm index 6de8704..8d21823 100644 --- a/shared_array.htm +++ b/shared_array.htm @@ -1,188 +1,223 @@ + + + shared_array - - --
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_ptr +
+ +
shared_array class template
The shared_array class template stores a pointer to a dynamically allocated +array. (Dynamically allocated array are allocated with the C++ new[] +expression.) The object pointed to is guaranteed to be deleted when +the last shared_array pointing to it is destroyed or reset.
+ +Every shared_array meets the CopyConstructible +and Assignable requirements of the C++ Standard Library, and so +can be used in standard library containers. Comparison operators +are supplied so that shared_array works with +the standard library's associative containers.
+ +Normally, a shared_array cannot correctly hold a pointer to a +dynamically allocated array. See shared_ptr 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 C++ Standard Library vector is a -heavier duty alternative to a shared_array.
-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 { ++ +Because the implementation uses reference counting, shared_array will not work +correctly with cyclic data structures. For example, if main() holds a shared_array +to A, which directly or indirectly holds a shared_array back to A, +A's use count will be 2. Destruction of the original shared_array +will leave A dangling with a use count of 1.
- public: - typedef T element_type; +A shared_ptr to a std::vector is an alternative to a shared_array that is +a bit heavier duty but far more flexible.
- explicit shared_array( T* p=0 ); - shared_array( const shared_array& ); // never throws - ~shared_array(); +The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements.
- shared_array& operator=( const shared_array& ); // never throws +Synopsis
- void reset( T* p=0 ); +namespace boost { - T& operator[](std::size_t i) const; // never throws - T* get() const; // never throws + template<typename T> class shared_array { - long use_count() const; // never throws - bool unique() const; // never throws + public: + typedef T element_type; - void swap( shared_array<T>& other ) throw() - }; + explicit shared_array(T * p = 0); + template<typename D> shared_array(T * p, D d); + ~shared_array(); // never throws -template<typename T> - inline bool operator==(const shared_array<T>& a, const shared_array<T>& b) - { return a.get() == b.get(); } + shared_array(shared_array const & r); // never throws -template<typename T> - inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b) - { return a.get() != b.get(); } -}-namespace std { + shared_array & operator=(shared_array const & r); // never throws -template<typename T> - inline void swap(boost::shared_array<T>& a, boost::shared_array<T>& b) - { a.swap(b); } + void reset(T * p = 0); // never throws + template<typename D> void reset(T * p, D d); // never throws -template<typename T> - struct less< boost::shared_array<T> > - : binary_function<boost::shared_array<T>, boost::shared_array<T>, bool> - { - bool operator()(const boost::shared_array<T>& a, - const boost::shared_array<T>& b) const - { return less<T*>()(a.get(),b.get()); } + T & operator[](std::ptrdiff_t i) const() const; // never throws + T * get() const; // never throws + + bool unique() const; // never throws + long use_count() const; // never throws + + void swap(shared_array<T> & b); // never throws }; -} // 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
+ template<typename T> + bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws + template<typename T> + bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws + template<typename T> + bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws + + template<typename T> void swap(shared_array<T> & a, shared_array<T> & b); // never throws + +}Members
+ +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 + +
constructors
+ +explicit shared_array(T * p = 0);+Constructs a shared_array, storing a copy of p, which +must be a pointer to an array that was allocated via a C++ new[] expression or be 0. +Afterwards, the use count is 1 (even if p == 0; see ~shared_array). +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, delete[] p is called.
+ +template<typename D> shared_array(T * p, D d);+Constructs a shared_array, storing a copy of p and of d. +Afterwards, the use count is 1. +D's copy constructor must not throw. +When the the time comes to delete the array pointed to by p, the object +d is used in the statement d(p). Invoking the object d with +parameter p in this way must not throw. +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, d(p) is called.
+ +shared_array(shared_array const & r); // never throws+Constructs a shared_array, as if by storing a copy of the +pointer stored in r. Afterwards, the use count +for all copies is 1 more than the initial use count.
+ +destructor
+ +~shared_array(); // never throws+Decrements the use count. Then, if the use count is 0, +deletes the array pointed to by the stored pointer. +Note that delete[] on a pointer with a value of 0 is harmless. +T need not be a complete type. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements.
+ +assignment
+ +shared_array & operator=(shared_array const & r); // never throws+Constructs a new shared_array as described above, +then replaces this shared_array with the new one, destroying the replaced object.
+ +reset
+ +void reset(T * p = 0);+Constructs a new shared_array as described above, +then replaces this shared_array with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, delete[] p is called.
+ +template<typename D> void reset(T * p, D d);+Constructs a new shared_array as described above, +then replaces this shared_array with the new one, destroying the replaced object. +D's copy constructor must not throw. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, d(p) is called.
+ +indexing
+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 the stored pointer is 0, +or if i is less than 0 or is greater than or equal to the number of elements in the array.
-shared_array get
-T* get() const; // never throws-T is not required be a complete type. -See Common Requirements.
-Returns the stored pointer.
-shared_array use_count
-long use_count() const; // never throws
-T is not required be a complete type. -See Common Requirements.
-Returns the number of shared_arrays sharing ownership of the -stored pointer.
-shared_array unique
-bool unique() const; // never throws
-T is not required be a complete type. -See Common Requirements.
-Returns use_count() == 1.
-shared_array swap
--
void swap( shared_array<T>& other ) throw()
T is not required be a complete type. -See Common Requirements.
-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.]
+ +get
+T * get() const; // never throws+Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.
+ +unique
+bool unique() const; // never throws+Returns true if no other shared_array is sharing ownership of +the stored pointer, false otherwise. +T need not be a complete type. +See the smart pointer +common requirements.
+ +use_count
+long use_count() const; // never throws+Returns the number of shared_array objects sharing ownership of the +stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.
+Because use_count is not necessarily efficient to implement for +implementations of shared_array that do not use an explicit reference +count, it might be removed from some future version. Thus it should +be used for debugging purposes only, and not production code.
+ +swap
+void swap(shared_ptr & b); // never throws+Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.
+ +Free Functions
+ +comparison
+template<typename T> + bool operator==(shared_array<T> const & a, shared_array<T> const & b); // never throws +template<typename T> + bool operator!=(shared_array<T> const & a, shared_array<T> const & b); // never throws +template<typename T> + bool operator<(shared_array<T> const & a, shared_array<T> const & b); // never throws+Compares the stored pointers of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.
+The operator< overload is provided to define an ordering so that shared_array +objects can be used in associative containers such as std::map. +The implementation uses std::less<T*> to perform the +comparison. This ensures that the comparison is handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).
+ +swap
+template<typename T> + void swap(shared_array<T> & a, shared_array<T> & b) // never throws+Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.
+
-Revised 24 May, 2001 -
-© 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.
+ +Revised 1 February 2002
+ +Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +Permission to copy, use, modify, sell and distribute this document is granted +provided this copyright notice appears in all copies. +This document is provided "as is" without express or implied warranty, +and with no claim as to its suitability for any purpose.
diff --git a/shared_ptr.htm b/shared_ptr.htm index 4913f65..fc6d0d6 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -1,284 +1,356 @@ + + +shared_ptr - - --
-Class -shared_ptr
+ +
shared_ptr class template
Introduction
+
+Synopsis
Members
-Example
+Free Functions
+Example
Handle/Body Idiom
Frequently Asked Questions
Smart Pointer TimingsIntroduction
-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 + +
The shared_ptr class template 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 destroyed or reset. +See the example.
+ +Every shared_ptr meets the CopyConstructible +and Assignable requirements of the C++ Standard Library, and so +can be used in standard library containers. Comparison operators +are supplied so that shared_ptr works with +the standard library's associative containers.
+ +Normally, a 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 { ++ +Because the implementation uses reference counting, shared_ptr will not work +correctly with cyclic data structures. For example, if main() holds a shared_ptr +to A, which directly or indirectly holds a shared_ptr back to A, +A's use count will be 2. Destruction of the original shared_ptr +will leave A dangling with a use count of 1.
- public: - typedef T element_type; +The class template is parameterized on T, the type of the object +pointed to. T must meet the smart pointer +common requirements. +T may be void, but in that case, either an explicit delete +function must be passed in, or the pointed-to object must have a trivial destructor.
- explicit shared_ptr( T* p=0 ); - ~shared_ptr(); +Synopsis
- 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); +namespace boost { - 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); + template<typename T> class shared_ptr { - void reset( T* p=0 ); + public: + typedef T element_type; - T& operator*() const; // never throws - T* operator->() const; // never throws - T* get() const; // never throws + explicit shared_ptr(T * p = 0); + template<typename D> shared_ptr(T * p, D d); + ~shared_ptr(); // never throws - long use_count() const; // never throws - bool unique() const; // never throws + shared_ptr(shared_ptr const & r); // never throws + template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws + template<typename Y> shared_ptr(std::auto_ptr<Y> & r); - void swap( shared_ptr<T>& other ) throw() - }; + shared_ptr & operator=(shared_ptr const & r); // never throws + template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws + template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r); -template<typename T, typename U> - inline bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) - { return a.get() == b.get(); } + void reset(T * p = 0); // never throws + template<typename D> void reset(T * p, D d); // never throws -template<typename T, typename U> - inline bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) - { return a.get() != b.get(); } -}-namespace std { + T & operator*() const; // never throws + T * operator->() const; // never throws + T * get() const; // never throws -template<typename T> - inline void swap(boost::shared_ptr<T>& a, boost::shared_ptr<T>& b) - { a.swap(b); } + bool unique() const; // never throws + long use_count() const; // never throws -template<typename T> - struct less< boost::shared_ptr<T> > - : binary_function<boost::shared_ptr<T>, boost::shared_ptr<T>, bool> - { - bool operator()(const boost::shared_ptr<T>& a, - const boost::shared_ptr<T>& b) const - { return less<T*>()(a.get(),b.get()); } + void swap(shared_ptr<T> & b); // never throws }; -} // 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
+ template<typename T, typename U> + bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + template<typename T, typename U> + bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + template<typename T, typename U> + bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + + template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws + + template<typename T, typename U> + shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws + template<typename T, typename U> + shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r); + +}Members
+ +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-T is not required by get() to be a complete type . See Common Requirements.
-Both return the stored pointer.
-shared_ptr use_count
-long use_count() const; // never throws
-T is not required be a complete type. -See Common Requirements.
-Returns the number of shared_ptrs sharing ownership of the -stored pointer.
-shared_ptr unique
-bool unique() const; // never throws
-T is not required be a complete type. -See Common Requirements.
-Returns use_count() == 1.
-shared_ptr swap
--
void swap( shared_ptr<T>& other ) throw()
T is not required be a complete type. -See Common Requirements.
-Swaps the two smart pointers, as if by std::swap.
-Class shared_ptr example
-See shared_ptr_example.cpp for a complete example program.
-This program builds a std::vector and std::set of FooPtr's.
-Note that after the two containers have been populated, some of the FooPtr objects -will have use_count()==1 rather than use_count()==2, since foo_set is a std::set -rather than a std::multiset, and thus does not contain duplicate entries. Furthermore, use_count() may be even higher -at various times while push_back() and insert() container operations are performed. + +
constructors
+ +explicit shared_ptr(T * p = 0);+Constructs a shared_ptr, storing a copy of p, which +must be a pointer to an object that was allocated via a C++ new expression or be 0. +Afterwards, the 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.
+ +template<typename D> shared_ptr(T * p, D d);+Constructs a shared_ptr, storing a copy of p and of d. +Afterwards, the use count is 1. +D's copy constructor must not throw. +When the the time comes to delete the object pointed to by p, the object +d is used in the statement d(p). Invoking the object d with +parameter p in this way must not throw. +The only exception which may be thrown by this constructor is std::bad_alloc. +If an exception is thrown, d(p) is called.
+ +shared_ptr(shared_ptr const & r); // never throws +template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws +template<typename Y> shared_ptr(std::auto_ptr<Y> & r);+Constructs a shared_ptr, as if by storing a copy of the +pointer stored in r. Afterwards, the use count +for all copies is 1 more than the initial 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 is std::bad_alloc, +which may be thrown during construction from auto_ptr. +If an exception is thrown, the constructor has no effect.
+ +destructor
+ +~shared_ptr(); // never throws+Decrements the use count. Then, if the use count is 0, +deletes the object pointed to by the stored pointer. +Note that delete on a pointer with a value of 0 is harmless. +T need not be a complete type. +The guarantee that this does not throw exceptions depends on the requirement that the +deleted object's destructor does not throw exceptions. +See the smart pointer common requirements.
+ +assignment
+ +shared_ptr & operator=(shared_ptr const & r); // never throws +template<typename Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws +template<typename Y> shared_ptr & operator=(std::auto_ptr<Y> & r);+Constructs a new shared_ptr as described above, +then replaces this shared_ptr with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc, +which may be thrown during assignment from auto_ptr. +If an exception is thrown, the assignment has no effect.
+ +reset
+ +void reset(T * p = 0);+Constructs a new shared_ptr as described above, +then replaces this shared_ptr with the new one, destroying the replaced object. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, delete p is called.
+ +template<typename D> void reset(T * p, D d);+Constructs a new shared_ptr as described above, +then replaces this shared_ptr with the new one, destroying the replaced object. +D's copy constructor must not throw. +The only exception which may be thrown is std::bad_alloc. If +an exception is thrown, d(p) is called.
+ +indirection
+T & operator*() const; // never throws+Returns a reference to the object pointed to by the stored pointer. +Behavior is undefined if the stored pointer is 0.
+T * operator->() const; // never throws+Returns the stored pointer. Behavior is undefined if the stored pointer is 0.
+ +get
+T * get() const; // never throws+Returns the stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.
+ +unique
+bool unique() const; // never throws+Returns true if no other shared_ptr is sharing ownership of +the stored pointer, false otherwise. +T need not be a complete type. +See the smart pointer +common requirements.
+ +use_count
+long use_count() const; // never throws+Returns the number of shared_ptr objects sharing ownership of the +stored pointer. +T need not be a complete type. +See the smart pointer +common requirements.
+Because use_count is not necessarily efficient to implement for +implementations of shared_ptr that do not use an explicit reference +count, it might be removed from some future version. Thus it should +be used for debugging purposes only, and not production code.
+ +swap
+void swap(shared_ptr & b); // never throws+Exchanges the contents of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.
+ +Free Functions
+ +comparison
+template<typename T, typename U> + bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws +template<typename T, typename U> + bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws +template<typename T, typename U> + bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws+Compares the stored pointers of the two smart pointers. +T need not be a complete type. +See the smart pointer +common requirements.
+The operator< overload is provided to define an ordering so that shared_ptr +objects can be used in associative containers such as std::map. +The implementation uses std::less<T*> to perform the +comparison. This ensures that the comparison is handled correctly, since the +standard mandates that relational operations on pointers are unspecified (5.9 [expr.rel] +paragraph 2) but std::less<> on pointers is well-defined (20.3.3 [lib.comparisons] +paragraph 8).
+ +swap
+template<typename T> + void swap(shared_ptr<T> & a, shared_ptr<T> & b) // never throws+Equivalent to a.swap(b). Matches the interface of std::swap. +Provided as an aid to generic programming.
+ +shared_static_cast
+template<typename T, typename U> + shared_ptr<T> shared_static_cast(shared_ptr<U> const & r); // never throws+Perform a static_cast on the stored pointer, returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer.
+Note that the seemingly equivalent expression
++shared_ptr<T>(static_cast<T*>(r.get()))
will eventually result in undefined behavior, attempting to delete the same object twice.
+ +shared_dynamic_cast
+template<typename T, typename U> + shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r);+Perform a dynamic_cast on the stored pointer, returning another shared_ptr. +The resulting smart pointer will share its use count with the original pointer unless the result of the +cast is 0. The only exception which may be thrown is std::bad_alloc, which may be thrown during the +construction of the new shared_ptr if the result of the cast is 0. If an exception is thrown, the +cast has no effect.
+Note that the seemingly equivalent expression
++shared_ptr<T>(dynamic_cast<T*>(r.get()))
will eventually result in undefined behavior, attempting to delete the same object twice.
+ +Example
+ +See shared_ptr_example.cpp for a complete example program. +The program builds a std::vector and std::set of shared_ptr objects.
+ +Note that after the containers have been populated, some of the shared_ptr objects +will have a use count of 1 rather than a use count of 2, since the set is a std::set +rather than a std::multiset, and thus does not contain duplicate entries. +Furthermore, the use count may be even higher +at various times while push_back and insert container operations are performed. More complicated yet, the container operations may throw exceptions under a -variety of circumstances. Without using a smart pointer, memory and -exception management would be a nightmare.
+variety of circumstances. Getting the memory management and exception handling in this +example right without a smart pointer would be a nightmare. +Handle/Body Idiom
+One common usage of shared_ptr is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.
+The shared_ptr_example2_test.cpp sample program includes a header file, shared_ptr_example2.hpp, which uses a shared_ptr<> to an incomplete type to hide the -implementation. The -instantiation of member functions which require a complete type occurs in the shared_ptr_example2.cpp -implementation file.
+implementation. The +instantiation of member functions which require a complete type occurs in the +shared_ptr_example2.cpp +implementation file. +Note that there is no need for an explicit destructor. +Unlike ~scoped_ptr, ~shared_ptr does not require that T be a complete type. +Frequently Asked Questions
+Q. Why doesn't shared_ptr have template parameters supplying traits or policies to allow extensive user customization?
+Some day a highly configurable smart pointer may be invented that is also very +easy to use and very hard to misuse. Until then, shared_ptr is the +smart pointer of choice for a wide range of applications. (Those +interested in policy based smart pointers should read +Modern C++ Design by Andrei Alexandrescu.) +
-A. Parameterization discourages users. Shared_ptr is +A. Parameterization discourages users. The shared_ptr template is carefully crafted to meet common needs without extensive parameterization. -Someday a highly configurable smart pointer may be invented that is also very -easy to use and very hard to misuse. Until then, shared_ptr is the -smart pointer of choice for a wide range of applications. (Those -interested in policy based smart pointers should read Modern -C++ Design by Andrei Alexandrescu.)Q. Why doesn't shared_ptr use a linked list implementation?
-
A. A linked list implementation does not offer enough advantages to -offset the added cost of an extra pointer. See timings +offset the added cost of an extra pointer. See timings page.Q. Why don't shared_ptr (and the other Boost smart pointers) + +
Q. Why doesn't shared_ptr (or any of the other Boost smart pointers) supply an automatic conversion to T*?
+
A. Automatic conversion is believed to be too error prone.Q. Why does shared_ptr supply use_count()?
+
A. As an aid to writing test cases and debugging displays. One of the progenitors had use_count(), and it was useful in tracking down bugs in a complex project that turned out to have cyclic-dependencies.Q. Why doesn't shared_ptr specify complexity requirements?
+
-A. Because complexity limit implementors and complicate the specification without apparent benefit to -shared_ptr users. For example, error-checking implementations might become non-conforming if they +A. Because complexity requirements limit implementors and complicate the +specification without apparent benefit to shared_ptr users. +For example, error-checking implementations might become non-conforming if they had to meet stringent complexity requirements.Q. Why doesn't shared_ptr provide a release() function?
A. shared_ptr cannot give away ownership unless it's unique() because the other copy will still destroy the object.Consider:
--+shared_ptr<int> a(new int); +-shared_ptr<int> a(new int); shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2 int * p = a.release(); -// Who owns p now? b will still call delete on it in its destructor.-[Provided by Peter Dimov]
+// Who owns p now? b will still call delete on it in its destructor.Q. Why doesn't shared_ptr provide (your pet feature here)?
-
-A. Because (your pet feature here) would mandate a reference counted (or a link-list, or ...) implementation. This is not the intent. -[Provided by Peter Dimov]+A. Because (your pet feature here) would mandate a reference counted +implementation or a linked list implementation, or some other specific implementation. +This is not the intent. +
-
-Revised 11 January, 2002 -
-© 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.
+ +Revised 1 February 2002
+ +Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +Permission to copy, use, modify, sell and distribute this document is granted +provided this copyright notice appears in all copies. +This document is provided "as is" without express or implied warranty, +and with no claim as to its suitability for any purpose.
- \ No newline at end of file + diff --git a/shared_ptr_example.cpp b/shared_ptr_example.cpp index 988efbd..4db8fc6 100644 --- a/shared_ptr_example.cpp +++ b/shared_ptr_example.cpp @@ -20,7 +20,7 @@ #include#include #include -#include +#include // The application will produce a series of // objects of type Foo which later must be diff --git a/shared_ptr_example2.cpp b/shared_ptr_example2.cpp index eddc806..746dd48 100644 --- a/shared_ptr_example2.cpp +++ b/shared_ptr_example2.cpp @@ -17,5 +17,3 @@ example & example::operator=( const example & s ) void example::do_something() { std::cout << "use_count() is " << _imp.use_count() << "\n"; } - -example::~example() {} diff --git a/shared_ptr_example2.hpp b/shared_ptr_example2.hpp index fea810b..93b77e5 100644 --- a/shared_ptr_example2.hpp +++ b/shared_ptr_example2.hpp @@ -1,6 +1,6 @@ // Boost shared_ptr_example2 header file -----------------------------------// -#include +#include // This example demonstrates the handle/body idiom (also called pimpl and // several other names). It separates the interface (in this header file) @@ -16,7 +16,6 @@ class example { public: example(); - ~example(); example( const example & ); example & operator=( const example & ); void do_something(); diff --git a/smart_ptr.htm b/smart_ptr.htm index 07538e4..0f5246d 100644 --- a/smart_ptr.htm +++ b/smart_ptr.htm @@ -1,126 +1,175 @@ + + - - - Smart Pointer Classes +Smart Pointers -
Smart +
-
Smart Pointers
Smart pointers are classes which store pointers to dynamically allocated -(heap) objects. They behave much like built-in C++ pointers except that + +
Smart pointers are objects which store pointers to dynamically allocated +(heap) objects. They behave much like built-in C++ pointers except that they automatically delete the object pointed to at the appropriate -time. Smart pointers are particularly useful in the face of exceptions as +time. Smart pointers are particularly useful in the face of exceptions as they ensure proper destruction of dynamically allocated objects. They can also be used to keep track of dynamically allocated objects shared by multiple owners.
+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:
+ +The smart pointer library provides five smart pointer class templates:
+-
- - +scoped_ptr +<boost/scoped_ptr.hpp> Simple sole ownership of single objects. Noncopyable. - scoped_array -Simple sole ownership of arrays. Noncopyable. +scoped_array +<boost/scoped_array.hpp> +Simple sole ownership of arrays. Noncopyable. - shared_ptr +shared_ptr +<boost/shared_ptr.hpp> Object ownership shared among multiple pointers - +shared_array +shared_array +<boost/shared_array.hpp> Array ownership shared among multiple pointers. + weak_ptr +<boost/weak_ptr.hpp> +Non-owning observers of an object owned by shared_ptr. +These classes are designed to complement the C++ Standard Library auto_ptr -class.
+ +These templates are designed to complement the std::auto_ptr template.
+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 + +
A test program, smart_ptr_test.cpp, is provided to verify correct operation.
-A page on Smart Pointer Timings will be of + +
A page on compatibility with older versions of +the Boost smart pointer library describes some of the changes since earlier versions +of the smart pointer implementation.
+ +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 throw exceptions.
-
T
may be an incomplete type at the point of smart pointer -declaration. Unless otherwise specified, it is required thatT
+ +Common Requirements
+ +These smart pointer class templates have a template parameter, T, which +specifies the type of the object pointed to by the smart pointer. The +behavior of the smart pointer templates is undefined if the destructor or operator delete +for objects of type T throw exceptions.
+ +T may be an incomplete type at the point of smart pointer +declaration. Unless otherwise specified, it is required that T be a complete type at points of smart pointer instantiation. Implementations are required to diagnose (treat as an error) all violations of this requirement, -including deletion of an incomplete type. See checked_delete().
+including deletion of an incomplete type. +See the description of the checked_delete +function template. +Rationale
-The requirements on T are carefully crafted to maximize safety -yet allow handle-body (also called pimpl) and similar idioms. In these idioms a -smart pointer may appear in translation units where T is an -incomplete type. This separates interface from implementation and hides -implementation from translation units which merely use the interface. + +
The requirements on T are carefully crafted to maximize safety +yet allow handle-body (also called pimpl) and similar idioms. In these idioms a +smart pointer may appear in translation units where T is an +incomplete type. This separates interface from implementation and hides +implementation from translation units which merely use the interface. Examples described in the documentation for specific smart pointers illustrate use of smart pointers in these idioms.
-Exception safety
+ +Note that scoped_ptr requires that T be a complete type +at destruction time, but shared_ptr does not.
+ +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 +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.
+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 + +
+Exception-specifications are not used; see +exception-specification rationale.
-All four classes contain member functions which can never throw exceptions, + +
All the smart pointer templates contain member functions which can never throw exceptions, because they neither throw exceptions themselves nor call other functions which -may throw exceptions. These members are indicated by a comment: // -never throws.
+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
-May, 2001. Vladimir Prus suggested requiring a complete type on -destruction. Refinement evolved in discussions including Dave Abrahams, +throwing exceptions by the common requirements.
+ +History and Acknowledgements
+ +January 2002. Peter Dimov reworked all four classes, adding features, fixing bugs, +and splitting them into four separate headers, and added weak_ptr. See the +compatibility page for a summary of the changes.
+ +May 2001. Vladimir Prus suggested requiring a complete type on +destruction. Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and others.
-November, 1999. Darin Adler provided operator ==, operator !=, and std::swap + +
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 + +
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 + +
October 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, +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, +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 +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, + +
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 +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: +
-
- Direct detached: the shared_ptr contains a pointer to the object, and a pointer to the count.
@@ -129,22 +178,29 @@ elsewhere. Each of those variants have themselves two major variants:- Embedded attached: the count is a member of the object pointed to.
- Placement attached: the count is attached via operator new manipulations.
Each implementation technique has advantages and disadvantages. We went + +
Each implementation technique has advantages and disadvantages. We went so far as to run various timings of the direct and indirect approaches, and found that at least on Intel Pentium chips there was very little measurable -difference. Kevlin Henney provided a paper he wrote on "Counted Body -Techniques." Dietmar Kühl suggested an elegant partial template +difference. Kevlin Henney provided a paper he wrote on "Counted Body +Techniques." Dietmar Kühl suggested an elegant partial template specialization technique to allow users to choose which implementation they preferred, and that was also experimented with.
+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 May 20011 February 2002
-© Copyright Greg Colvin and Beman Dawes 1999. Permission to copy, use, + +
Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. +Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for diff --git a/smart_ptr_test.cpp b/smart_ptr_test.cpp index 62c97ca..8d41070 100644 --- a/smart_ptr_test.cpp +++ b/smart_ptr_test.cpp @@ -13,13 +13,23 @@ // 20 Jul 99 header name changed to .hpp // 20 Apr 99 additional error tests added. +#include
+#include +#include +#include + #define BOOST_INCLUDE_MAIN #include -#include + #include #include #include +bool boost_error(char const *, char const *, char const *, long) +{ + return true; // fail with assert() +} + class Incomplete; Incomplete * get_ptr( boost::shared_ptr & incomplete ) @@ -48,7 +58,7 @@ class UDT { explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } ~UDT() { --UDT_use_count; - cout << "UDT with value " << value_ << " being destroyed" << endl; + cout << "UDT with value " << value_ << " being destroyed\n"; } long value() const { return value_; } void value( long v ) { value_ = v;; } @@ -71,7 +81,7 @@ Incomplete * check_incomplete( shared_ptr & incomplete, shared_ptr & i2 ) { incomplete.swap(i2); - cout << incomplete.use_count() << " " << incomplete.unique() << endl; + cout << incomplete.use_count() << ' ' << incomplete.unique() << '\n'; return incomplete.get(); } // main --------------------------------------------------------------------// @@ -186,12 +196,10 @@ int test_main( int, char ** ) { BOOST_TEST( *cp4 == 87654 ); BOOST_TEST( cp2.get() == 0 ); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_ptr > scp; scp.insert(cp4); BOOST_TEST( scp.find(cp4) != scp.end() ); BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr (cp4) ) ); -#endif // test shared_array with a built-in type char * cap = new char [ 100 ]; @@ -232,12 +240,10 @@ int test_main( int, char ** ) { BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); BOOST_TEST( ca3.get() == 0 ); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION set< shared_array > sca; sca.insert(ca4); BOOST_TEST( sca.find(ca4) != sca.end() ); BOOST_TEST( sca.find(ca4) == sca.find( shared_array (ca4) ) ); -#endif // test shared_array with user defined type shared_array udta ( new UDT[3] ); @@ -280,7 +286,7 @@ int test_main( int, char ** ) { BOOST_TEST( sup.use_count() == 2 ); BOOST_TEST( sup2.use_count() == 2 ); - cout << "OK" << endl; + cout << "OK\n"; new char[12345]; // deliberate memory leak to verify leaks detected diff --git a/smart_ptr_test2.cpp b/smart_ptr_test2.cpp deleted file mode 100644 index 4ea305e..0000000 --- a/smart_ptr_test2.cpp +++ /dev/null @@ -1,295 +0,0 @@ -// smart pointer test program ----------------------------------------------// - -// (C) Copyright Beman Dawes 1998, 1999. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright notice -// appears in all copies. This software is provided "as is" without express or -// implied warranty, and with no claim as to its suitability for any purpose. - -// Revision History -// 24 May 01 use Boost test library for error detection, reporting, add tests -// for operations on incomplete types (Beman Dawes) -// 29 Nov 99 added std::swap and associative container tests (Darin Adler) -// 25 Sep 99 added swap tests -// 20 Jul 99 header name changed to .hpp -// 20 Apr 99 additional error tests added. - -#include -#include -#include -#include - -#define BOOST_INCLUDE_MAIN -#include - -#include -#include -#include - -bool boost_error(char const *, char const *, char const *, long) -{ - return true; // fail with assert() -} - -class Incomplete; - -Incomplete * get_ptr( boost::shared_ptr & incomplete ) -{ - return incomplete.get(); -} - -using namespace std; -using boost::scoped_ptr; -using boost::scoped_array; -using boost::shared_ptr; -using boost::shared_array; - -template -void ck( const T* v1, T v2 ) { BOOST_TEST( *v1 == v2 ); } - -namespace { - int UDT_use_count; // independent of pointer maintained counts - } - -// user defined type -------------------------------------------------------// - -class UDT { - long value_; - public: - explicit UDT( long value=0 ) : value_(value) { ++UDT_use_count; } - ~UDT() { - --UDT_use_count; - cout << "UDT with value " << value_ << " being destroyed" << endl; - } - long value() const { return value_; } - void value( long v ) { value_ = v;; } - }; // UDT - -// tests on incomplete types -----------------------------------------------// - -// Certain smart pointer operations are specified to work on incomplete types, -// and some uses depend upon this feature. These tests verify compilation -// only - the functions aren't actually invoked. - -class Incomplete; - -Incomplete * check_incomplete( scoped_ptr & incomplete ) -{ - return incomplete.get(); -} - -Incomplete * check_incomplete( shared_ptr & incomplete, - shared_ptr & i2 ) -{ - incomplete.swap(i2); - cout << incomplete.use_count() << " " << incomplete.unique() << endl; - return incomplete.get(); -} -// main --------------------------------------------------------------------// - -// This isn't a very systematic test; it just hits some of the basics. - -int test_main( int, char ** ) { - - BOOST_TEST( UDT_use_count == 0 ); // reality check - - // test scoped_ptr with a built-in type - long * lp = new long; - scoped_ptr sp ( lp ); - BOOST_TEST( sp.get() == lp ); - BOOST_TEST( lp == sp.get() ); - BOOST_TEST( &*sp == lp ); - - *sp = 1234568901L; - BOOST_TEST( *sp == 1234568901L ); - BOOST_TEST( *lp == 1234568901L ); - ck( static_cast (sp.get()), 1234568901L ); - ck( lp, *sp ); - - sp.reset(); - BOOST_TEST( sp.get() == 0 ); - - // test scoped_ptr with a user defined type - scoped_ptr udt_sp ( new UDT( 999888777 ) ); - BOOST_TEST( udt_sp->value() == 999888777 ); - udt_sp.reset(); - udt_sp.reset( new UDT( 111222333 ) ); - BOOST_TEST( udt_sp->value() == 111222333 ); - udt_sp.reset( new UDT( 333222111 ) ); - BOOST_TEST( udt_sp->value() == 333222111 ); - - // test scoped_array with a build-in type - char * sap = new char [ 100 ]; - scoped_array sa ( sap ); - BOOST_TEST( sa.get() == sap ); - BOOST_TEST( sap == sa.get() ); - - strcpy( sa.get(), "Hot Dog with mustard and relish" ); - BOOST_TEST( strcmp( sa.get(), "Hot Dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( sap, "Hot Dog with mustard and relish" ) == 0 ); - - BOOST_TEST( sa[0] == 'H' ); - BOOST_TEST( sa[30] == 'h' ); - - sa[0] = 'N'; - sa[4] = 'd'; - BOOST_TEST( strcmp( sap, "Not dog with mustard and relish" ) == 0 ); - - sa.reset(); - BOOST_TEST( sa.get() == 0 ); - - // test shared_ptr with a built-in type - int * ip = new int; - shared_ptr cp ( ip ); - BOOST_TEST( ip == cp.get() ); - BOOST_TEST( cp.use_count() == 1 ); - - *cp = 54321; - BOOST_TEST( *cp == 54321 ); - BOOST_TEST( *ip == 54321 ); - ck( static_cast (cp.get()), 54321 ); - ck( static_cast (ip), *cp ); - - shared_ptr cp2 ( cp ); - BOOST_TEST( ip == cp2.get() ); - BOOST_TEST( cp.use_count() == 2 ); - BOOST_TEST( cp2.use_count() == 2 ); - - BOOST_TEST( *cp == 54321 ); - BOOST_TEST( *cp2 == 54321 ); - ck( static_cast (cp2.get()), 54321 ); - ck( static_cast (ip), *cp2 ); - - shared_ptr cp3 ( cp ); - BOOST_TEST( cp.use_count() == 3 ); - BOOST_TEST( cp2.use_count() == 3 ); - BOOST_TEST( cp3.use_count() == 3 ); - cp.reset(); - BOOST_TEST( cp2.use_count() == 2 ); - BOOST_TEST( cp3.use_count() == 2 ); - BOOST_TEST( cp.use_count() == 1 ); - cp.reset( new int ); - *cp = 98765; - BOOST_TEST( *cp == 98765 ); - *cp3 = 87654; - BOOST_TEST( *cp3 == 87654 ); - BOOST_TEST( *cp2 == 87654 ); - cp.swap( cp3 ); - BOOST_TEST( *cp == 87654 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( *cp3 == 98765 ); - cp.swap( cp3 ); - BOOST_TEST( *cp == 98765 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( *cp3 == 87654 ); - cp2 = cp2; - BOOST_TEST( cp2.use_count() == 2 ); - BOOST_TEST( *cp2 == 87654 ); - cp = cp2; - BOOST_TEST( cp2.use_count() == 3 ); - BOOST_TEST( *cp2 == 87654 ); - BOOST_TEST( cp.use_count() == 3 ); - BOOST_TEST( *cp == 87654 ); - - shared_ptr cp4; - swap( cp2, cp4 ); - BOOST_TEST( cp4.use_count() == 3 ); - BOOST_TEST( *cp4 == 87654 ); - BOOST_TEST( cp2.get() == 0 ); - - set< shared_ptr > scp; - scp.insert(cp4); - BOOST_TEST( scp.find(cp4) != scp.end() ); - BOOST_TEST( scp.find(cp4) == scp.find( shared_ptr (cp4) ) ); - - // test shared_array with a built-in type - char * cap = new char [ 100 ]; - shared_array ca ( cap ); - BOOST_TEST( ca.get() == cap ); - BOOST_TEST( cap == ca.get() ); - BOOST_TEST( &ca[0] == cap ); - - strcpy( ca.get(), "Hot Dog with mustard and relish" ); - BOOST_TEST( strcmp( ca.get(), "Hot Dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( cap, "Hot Dog with mustard and relish" ) == 0 ); - - BOOST_TEST( ca[0] == 'H' ); - BOOST_TEST( ca[30] == 'h' ); - - shared_array ca2 ( ca ); - shared_array ca3 ( ca2 ); - - ca[0] = 'N'; - ca[4] = 'd'; - BOOST_TEST( strcmp( ca.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( ca2.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( strcmp( ca3.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( ca.use_count() == 3 ); - BOOST_TEST( ca2.use_count() == 3 ); - BOOST_TEST( ca3.use_count() == 3 ); - ca2.reset(); - BOOST_TEST( ca.use_count() == 2 ); - BOOST_TEST( ca3.use_count() == 2 ); - BOOST_TEST( ca2.use_count() == 1 ); - - ca.reset(); - BOOST_TEST( ca.get() == 0 ); - - shared_array ca4; - swap( ca3, ca4 ); - BOOST_TEST( ca4.use_count() == 1 ); - BOOST_TEST( strcmp( ca4.get(), "Not dog with mustard and relish" ) == 0 ); - BOOST_TEST( ca3.get() == 0 ); - - set< shared_array > sca; - sca.insert(ca4); - BOOST_TEST( sca.find(ca4) != sca.end() ); - BOOST_TEST( sca.find(ca4) == sca.find( shared_array