auto_ptr class template — Smart pointer to manage ownership of pointers
template <class T> struct auto_ptr_ref {}; template<class T> class auto_ptr { public: typedef T element_type; explicit auto_ptr(T* p = 0) throw( ); auto_ptr(auto_ptr&) throw( ); template<class U> auto_ptr(auto_ptr<U>&) throw( ); auto_ptr(auto_ptr_ref<T>) throw( ); ~auto_ptr( ) throw( ); auto_ptr& operator=(auto_ptr&) throw( ); template<class U> auto_ptr& operator=(auto_ptr<U>&) throw( ); auto_ptr& operator=(auto_ptr_ref<T> r) throw( ); T& operator*( ) const throw( ); T* operator->( ) const throw( ); T* get( ) const throw( ); T* release( ) throw( ); void reset(T* p = 0) throw( ); template<class U> operator auto_ptr_ref<U>( ) throw( ); template<class U> operator auto_ptr<U>( ) throw( ); };
The auto_ptr
class template
implements a smart pointer to manage ownership of pointers. Proper
use of auto_ptr
ensures that a
pointer has exactly one owner (which prevents accidental double
deletes), and the owner automatically frees the memory when the
owner goes out of scope (which prevents memory leaks). Assignment of
auto_ptr
values transfers
ownership from the source to the target of the assignment.
The auto_ptr_ref
type holds
a reference to an auto_ptr
.
Implicit conversions between auto_ptr
and auto_ptr_ref
facilitate the return of
auto_ptr
objects from functions.
Usually, you can ignore the auto_ptr_ref
type and let the implicit
conversions handle the details for you. All you need to do is use
auto_ptr
as a return type. The
details of auto_ptr_ref
are
implementation-defined.
Some of the typical uses for auto_ptr
are:
Data members of pointer type that point to dynamically
allocated objects are prime candidates for auto_ptr
, which ensures that the
memory is properly freed when the owning object is destroyed.
Be sure to implement a copy constructor and assignment
operator for any class that uses auto_ptr<>
for its data
members.
If a function must dynamically allocate a temporary
object, store the pointer in an auto_ptr
variable. When the function
returns (normally or as the result of an exception), the
object is destroyed automatically. This can drastically reduce
the need for try
-catch
statements.
In a complex program, objects are frequently allocated
in one part of the program and freed in another. It can be
difficult to keep track of when it is safe or proper to free
an object. Using auto_ptr
,
you can safely ensure that each object has exactly one owner,
and ownership is properly passed via assignment and function
calls. When the object is no longer needed, it is freed
automatically.
Because you cannot simply copy or assign an auto_ptr
, you cannot use auto_ptr
objects in a standard container.
Another limitation is that auto_ptr
cannot hold a pointer to an
array. Allocating and freeing a single object (e.g., new
int
) is different from allocating and
freeing an array of objects, (e.g., new
int[42]
), and auto_ptr
is designed to work only with
single objects.
A useful guideline is that a program should avoid bare
pointers (e.g., int*
x
). Bare pointers are error-prone: they
are subject to memory leaks, double-freeing, and dangling
references. Instead, use some form of ownership, such as auto_ptr<>
, or one of the Boost
smart pointers.
The Boost project has additional smart-pointer class templates that permit copying, arrays, and shared ownership. See Appendix B for more information about Boost.
Example 13-31
shows some uses of auto_ptr
.
Example 13-31. Sample uses of auto_ptr
class brush { . . . }; class pen { . . . }; // A function can return an auto_ptr<> object. std::auto_ptr<brush> default_brush( ) { return std::auto_ptr<brush>(new brush); } class DisplayContext { // Display or graphics context for drawing on a window. public: DisplayContext( ) : brush_(default_brush( )), pen_(new pen) {...} . . . private: // Make sure caller never tries to copy or assign // DisplayContext, but uses only objects that are // managed by auto_ptr<>. DisplayContext(const DisplayContext& dc); DisplayContext& operator=(const DisplayContext& dc); // Automatically manage lifetime of the pen and brush. // When the DisplayContext is freed, so are the pen // and brush instances. std::auto_ptr<brush> brush_; std::auto_ptr<pen> pen_; }; void repaint( ) { // Allocate a new display context. Use auto_ptr to ensure // that it will be freed automatically. std::auto_ptr<DisplayContext> dc(new DisplayContext( )); // Draw stuff on the display context. dc->draw( . . . ); // No need to call release; the display context is // automatically released when repaint( ) returns. } int main( ) { std::auto_ptr<DisplayContext> dc1(new DisplayContext); std::auto_ptr<DisplayContext> dc2(dc1); dc1 = dc2; repaint( ); }
The following are the members of auto_ptr
:
explicit
auto_ptr
(T* p = 0) throw(
)
Initializes the auto_ptr
object to own the pointer
p
.
auto_ptr
(auto_ptr& x) throw( )
, template<class
U>
auto_ptr
(auto_ptr<U>& x) throw(
)
Initializes the auto_ptr
object with the pointer
returned from x.release( )
.
In the second version, the type U*
must be implicitly convertible to
T*
. Note that x
is not const
. It is not possible to copy a
const
auto_ptr
because to do so would
break the ownership rules.
auto_ptr
(auto_ptr_ref<T> r) throw(
)
Initializes the auto_ptr
object with the pointer
obtained from calling release
on r
's auto_ptr
.
~auto_ptr
( )
throw(
)
Deletes the owned pointer (e.g., delete get( )
).
T*
get
( )
const
throw(
)
Returns the owned pointer.
T*
release
( )
throw( )
Returns get( )
and
resets the owned pointer to 0
.
void
reset
(T* p = 0)
throw( )
Deletes the owned pointer (if it is not equal to
p
) and saves p
as the new owned pointer.
template<class U>
operator
auto_ptr_ref<U
>( )
throw( )
Returns a temporary auto_ptr_ref
object that owns the
pointer. The pointer must be convertible to U*
. Ownership is released and
transferred to the new auto_ptr_ref
object.
template<class U>
operatorauto_ptr<U
>( )
throw( )
Returns a new auto_ptr
object. The owned pointer
is converted to type U*
,
and ownership is transferred to the new auto_ptr
object.
auto_ptr&
operator=
(auto_ptr&
x)
throw( )
, template<class
U>
, auto_ptr&
operator=
(auto_ptr<U>&
x)
throw( )
, auto_ptr&
operator=
(auto_ptr_ref<T>
r)
throw(
)
Transfers ownership of the pointer that is owned by
x
or by the auto_ptr
object held by r
to *this
. That is, it calls reset(x.release( ))
.
T&
operator*
( )
const
throw(
)
Returns *get( )
. If
the owned pointer is a null pointer, the behavior is
undefined.
T*
operator
->( )
const
throw( )
Returns get(
)
.