diff --git a/shared_ptr.htm b/shared_ptr.htm index 0cc96f1..be3b1c5 100644 --- a/shared_ptr.htm +++ b/shared_ptr.htm @@ -1,376 +1,423 @@ - +
+Introduction
+ Synopsis
+ Members
+ Free Functions
+ Example
+ Handle/Body Idiom
+ Frequently Asked Questions
+ Smart Pointer Timings
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.
+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.
+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.
+namespace boost { - - -shared_ptr - - - - -- -
shared_ptr class template
Introduction
- -
-Synopsis
-Members
-Free Functions
-Example
-Handle/Body Idiom
-Frequently Asked Questions
-Smart Pointer TimingsIntroduction
- -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.
- -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.
- -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.
- -Synopsis
- -namespace boost { + template<typename T> class weak_ptr; template<typename T> class shared_ptr { public: - typedef T element_type; + typedef T element_type; - explicit shared_ptr(T * p = 0); - template<typename D> shared_ptr(T * p, D d); - ~shared_ptr(); // never throws + explicit shared_ptr(T * p = 0); + template<typename D> shared_ptr(T * p, D d); + ~shared_ptr(); // 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); + shared_ptr(shared_ptr const & r); // never throws + template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws + shared_ptr(weak_ptr const & r); + template<typename Y> shared_ptr(std::auto_ptr<Y> & r); - 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); + 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); - void reset(T * p = 0); - template<typename D> void reset(T * p, D d); + void reset(T * p = 0); + template<typename D> void reset(T * p, D d); - T & operator*() const; // never throws - T * operator->() const; // never throws - T * get() const; // never throws + T & operator*() const; // never throws + T * operator->() const; // never throws + T * get() const; // never throws - bool unique() const; // never throws - long use_count() const; // never throws + bool unique() const; // never throws + long use_count() const; // never throws - void swap(shared_ptr<T> & b); // never throws + void swap(shared_ptr<T> & b); // never throws }; template<typename T, typename U> - bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws + 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 + bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws template<typename T> - bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws + bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b); // never throws - template<typename T> void swap(shared_ptr<T> & a, shared_ptr<T> & 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 + 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); + shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r); template<typename T, typename U> - shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r); + shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r); template<typename T, typename U> - shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws + shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws }- -Members
- -element_type
-typedef T element_type;-Provides the type of the stored pointer.
- -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 and destructor 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> +Members
+element_type
+typedef T element_type;+++Provides the type of the template parameter T.
+constructors
+explicit shared_ptr(T * p = 0);+++Requirements: The expression
+delete p
must be well-formed + and must not invoke undefined behavior. +Effects: Constructs a shared_ptr, storing a copy of p.
+Postconditions: use count is 1.
+Throws: std::bad_alloc.
+Exception safety: If an exception is thrown,
+delete p
is + called.Notes: p must be a pointer to an object that was + allocated via a C++ new expression or be 0. The postcondition that + use count is 1 holds even if p is 0; invoking delete + on a pointer that has a value of 0 is harmless.
+template<typename D> shared_ptr(T * p, D d);+++Requirements: The copy constructor and destructor of D must not + throw. The expression
+d(p)
must be well-formed, must not invoke + undefined behavior, and must not throw exceptions. +Effects: Constructs a shared_ptr, storing a copy of p and d.
+Postconditions: use count is 1.
+Throws: std::bad_alloc.
+Exception safety: If an exception is thrown,
+d(p)
is called.Notes: When the the time comes to delete the object pointed to by p, +
+d(p)
is invoked.shared_ptr(shared_ptr const & r); // never throws +template<typename Y> shared_ptr(shared_ptr<Y> const & r); // never throws+++Effects: Constructs a shared_ptr, as if by storing a copy of the + pointer stored in r.
+Postconditions: use count for all copies is + increased by one.
+Throws: nothing.
+shared_ptr(weak_ptr const & r);+++Effects: Constructs a shared_ptr, as if by storing a copy of the + pointer stored in r.
+Postconditions: use count for all copies is + increased by one.
+Throws: use_count_is_zero when
+r.use_count() == 0
.Exception safety: If an exception is thrown, the constructor has no + effect.
+template<typename Y> shared_ptr(std::auto_ptr<Y> & r);+++Effects: Constructs a shared_ptr, as if by storing a copy of r.release().
+Postconditions: use count for all copies is + increased by one.
+Throws: std::bad_alloc.
+Exception safety: If an exception is thrown, the constructor has no + effect.
+destructor
+~shared_ptr(); // never throws+++Effects: If *this is the sole owner (
+use_count() == 1
), + destroys the object pointed to by the stored pointer.Postconditions: use count for all remaining + copies is decreased by one.
+Throws: nothing.
+Notes: T need not be a complete type. The guarantee that the + destructor 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);+++Effects: Equivalent to
+shared_ptr(r).swap(*this)
.reset
+void reset(T * p = 0);+++Effects: Equivalent to
+shared_ptr(p).swap(*this)
.template<typename D> void reset(T * p, D d);+++Effects: Equivalent to
+shared_ptr(p, d).swap(*this)
.indirection
+T & operator*() const; // never throws+++Requirements: The stored pointer must not be 0.
+Returns: a reference to the object pointed to by the stored pointer.
+Throws: nothing.
+T * operator->() const; // never throws+++Requirements: The stored pointer must not be 0.
+Returns: the stored pointer.
+Throws: nothing.
+get
+T * get() const; // never throws+++Returns: the stored pointer.
+Throws: nothing.
+Notes: T need not be a complete type. See the smart pointer + common requirements.
+unique
+bool unique() const; // never throws+++Returns:
+use_count() == 1
.Throws: nothing.
+Notes:
+unique()
may be faster thanuse_count()
. 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.
+Throws: nothing.
+Notes:
+use_count()
is not necessarily efficient. Use only + for debugging and testing purposes, not for production code. T need not + be a complete type. See the smart pointer + common requirements.swap
+void swap(shared_ptr & b); // never throws+++Effects: Exchanges the contents of the two smart pointers.
+Throws: nothing.
+Notes: 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+++Returns:
+a.get() == b.get()
.Throws: nothing.
+Notes: T need not be a complete type. See the smart pointer + common requirements.
+template<typename T, typename U> + bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws+++Returns:
+a.get() != b.get()
.Throws: nothing.
+Notes: T need not be a complete type. See the smart pointer + common requirements.
+template<typename T> bool operator<(shared_ptr<T> const & a, shared_ptr<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_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> +++Returns: An implementation-defined value such that
+operator<
+ is a strict weak ordering as described in section 25.3[lib.alg.sorting]
+ of the C++ standard.Throws: nothing.
+Notes: Allows shared_ptr objects to be used as keys in + associative containers. T need not be a complete type. See the smart + pointer common requirements.
+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.
- -shared_polymorphic_cast
-template<typename T, typename U> - shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);-Perform a polymorphic_cast on the stored pointer, -returning another shared_ptr. -The resulting smart pointer will share its use count with the original pointer. -The only exception which may be thrown is std::bad_cast, if the pointer type can not be converted. -If an exception is thrown, the cast has no effect.
- -shared_polymorphic_downcast
-template<typename T, typename U> - shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws-Perform a polymorphic_downcast on the stored pointer, -returning another shared_ptr. -The resulting smart pointer will share its use count with the original pointer.
- -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. 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. -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?
- -
-A. Parameterization discourages users. The shared_ptr template is -carefully crafted to meet common needs without extensive parameterization. -Some day a highly configurable smart pointer may be invented that is also very -easy to use and very hard to misuse. Until then, 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 -page.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 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); ++++Effects: Equivalent to
+a.swap(b)
.Throws: nothing.
+Notes: 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+++Requires: The expression
+static_cast<T*>(r.get())
+ must be well-formed.Returns: A shared_ptr<T> object that stores a copy + of
+static_cast<T*>(r.get())
and shares ownership with r.Throws: nothing.
+Notes: 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);+++Requires: The expression
+dynamic_cast<T*>(r.get())
+ must be well-formed and its behavior defined.Returns:
++
+- + When
dynamic_cast<T*>(r.get())
returns a nonzero + value, a shared_ptr<T> object that stores a copy of + it and shares ownership with r; +- + Otherwise, a default-constructed shared_ptr<T> object.
Throws: std::bad_alloc.
+Exception safety: If an exception is thrown, the function has no + effect.
+Notes: 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.
+shared_polymorphic_cast
+template<typename T, typename U> + shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r);+++Requires: The expression
++ polymorphic_cast<T*>(r.get())
must be well-formed and + its behavior defined.Returns: A shared_ptr<T> object that stores a copy + of
+polymorphic_cast<T*>(r.get())
+ and shares ownership with r.Throws: std::bad_cast.
+Exception safety: If an exception is thrown, the function has no effect.
+shared_polymorphic_downcast
+template<typename T, typename U> + shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r); // never throws+++Requires: The expression
++ polymorphic_downcast<T*>(r.get())
must be well-formed + and its behavior defined.Returns: A shared_ptr<T> object that stores a copy + of
+polymorphic_downcast<T*>(r.get())
+ and shares ownership with r.Throws: nothing.
+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. 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. 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. There are several variations of shared pointers, with different + tradeoffs; why does the smart pointer library supply only a single + implementation? It would be useful to be able to experiment with each type so + as to find the most suitable for the job at hand?
+
+ A. An important goal of shared_ptr is to provide a + standard shared-ownership pointer. Having a single pointer type is important + for stable library interfaces, since different shared pointers typically cannot + interoperate, i.e. a reference counted pointer (used by library A) cannot share + ownership with a linked pointer (used by library B.)Q. Why doesn't shared_ptr have template parameters supplying + traits or policies to allow extensive user customization?
+
+ A. Parameterization discourages users. The shared_ptr template is + carefully crafted to meet common needs without extensive parameterization. Some + day a highly configurable smart pointer may be invented that is also very easy + to use and very hard to misuse. Until then, 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. I am not convinced. Default parameters can be use where appropriate to + hide the complexity. Again, why not policies?
+
+ A. Template parameters affect the type. See the answer to the first + question above.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 + page. In addition, it is expensive to make a linked list implementation thread + safe.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 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> 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.Q. Why doesn't shared_ptr provide (your pet feature here)?
- -
-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 8 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.
- - - +// 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 + implementation or a linked list implementation, or some other specific + implementation. This is not the intent.
+Revised + 14 February 2002
+Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. + Copyright 2002 Peter Dimov. 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.
+