boost.png (6897 bytes)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. Because it is noncopyable, it is safer than shared_ptr or std::auto_ptr for pointers which should not be copied.

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.

scoped_ptr cannot be used in C++ Standard Library containers. Use shared_ptr if you need a smart pointer that can.

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

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

Synopsis

namespace boost {

  template<class 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
     
     operator unspecified-bool-type() const; // never throws

     void swap(scoped_ptr & b); // never throws
  };

  template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b); // never throws

}

Members

element_type

typedef T element_type;

Provides the type of the stored pointer.

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

Destroys the object pointed to by the stored pointer, if any, as if by using delete this->get().

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 throws

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

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.

conversions

operator unspecified-bool-type () const; // never throws

Returns an unspecified value that, when used in boolean contexts, is equivalent to get() != 0.

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

int main()
{
    boost::scoped_ptr<Shoe> x(new Shoe);
    MyClass my_instance;
    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 shoe

Rationale

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

Frequently Asked Questions

Q. Why doesn't scoped_ptr have a release() member?
A. When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If scoped_ptr had a release() member, it would become possible to transfer ownership of the held pointer, weakening its role as a way of limiting resource lifetime to a given context. Use std::auto_ptr where transfer of ownership is required. (supplied by Dave Abrahams)


Revised 09 January 2003

Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler. Copyright 2002-2005 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.