ONLamp.com
oreilly.comSafari Books Online.Conferences.

advertisement


Smart Pointers in C++
Pages: 1, 2, 3, 4, 5

Smart Pointers in the Standard C++ Library

The standard C++ library comes with a smart pointer called auto_ptr, for "automatic pointer." It is very simple and is the least common denominator of smart pointers. No matter what, it is useful to make code more robust in many simple situations.



The auto_ptr smart pointer owns the object it holds a pointer to. That is, it releases the memory associated to it upon destruction; it does not do any allocation by itself, nor does it keep a reference counter of the memory involved.

The auto_ptr class overloads the * and -> operators so as to allow transparent access to the dynamic object. To access the raw pointer itself, use the get method. Consider a simple example:

std::auto_ptr<int> ptra(new int(5));

// From now on, the code is safe.  The dynamically allocated
// integer will be released no matter which execution path we
// follow.

*ptra = 4;
std::cout << *ptra << std::endl;
int* ptrb = ptra.get();
*ptrb = 3;
std::cout << *ptra << ", " << *ptrb
          << std::endl;

It is important to note in the example above that auto_ptr's constructor cannot fail. (It is declared as throws().) If it could, the code would need to be more complex in order to catch those failures, defeating in part the purpose of the smart pointer.

The automatic pointer also provides the release method, which detaches itself from the memory object, returning a raw pointer to it. This allows the use of an automatic pointer in a critical section only, falling back to manual management once that delicate code is over. As an example, imagine a function that returns a raw pointer to a dynamically allocated object. This function needs to do multiple initialization tasks and has several exit points if errors happen. You can use an automatic pointer to simplify its code:

foo *
get_new_foo(void)
{
    std::auto_ptr<foo> ob(new foo);

    // The following two operations can raise an exception.
    // We need not care about it thanks to the smart pointer.
    ob->do_something();
    ob->do_something_else();

    // We are done.  The caller is only interested in the raw
    // pointer, which we can safely return now.
    return ob.release();
}

Automatic pointers are not copyable. If the developer attempts to copy an instance of auto_ptr, the object it points to will be transferred to the new smart pointer, invalidating the old one. Therefore, using this class together with STL collections is dangerous; don't do it, because it does not follow the required semantics. Furthermore, if two automatic pointers hold a reference to the same memory object, the behavior is undefined (but typically the application will simply crash).

std::auto_ptr<int> ptra(new int(5));

// ptra is valid and can be accessed.
*ptra = 4;

std::auto_ptr<int> ptrb(ptra);

// ptrb now owns the dynamically allocated integer, so we can
// access it.
*ptrb = 3;

// However, ptra is now longer valid; the following crashes the
// program.
*ptra = 2;

// At last, the following has undefined behavior.
int* i = new int(1);
std::auto_ptr<int> ptrc(i);
std::auto_ptr<int> ptrd(i);

To conclude this section, let me add another warning: be aware that you cannot use auto_ptr to hold a reference to an array, because it will not be released properly (that is, delete vs. delete[]). If you need to do this, you have multiple alternatives: wrap the array in some other class of your own, use std::vector instead of an array, or use another smart pointer.

Pages: 1, 2, 3, 4, 5

Next Pagearrow





Sponsored by: