views:

3397

answers:

9

What is a smart pointer and when should I use one?

+5  A: 

http://en.wikipedia.org/wiki/Smart_pointer

In computer science, a smart pointer is an abstract data type that simulates a pointer while providing additional features, such as automatic garbage collection or bounds checking. These additional features are intended to reduce bugs caused by the misuse of pointers while retaining efficiency. Smart pointers typically keep track of the objects that point to them for the purpose of memory management. The misuse of pointers is a major source of bugs: the constant allocation, deallocation and referencing that must be performed by a program written using pointers makes it very likely that some memory leaks will occur. Smart pointers try to prevent memory leaks by making the resource deallocation automatic: when the pointer to an object (or the last in a series of pointers) is destroyed, for example because it goes out of scope, the pointed object is destroyed too.

smink
+1  A: 

A smart pointer is like a regular (typed) pointer, like "char*", except when the pointer itself goes out of scope then what it points to is deleted as well. You can use it like you would a regular pointer, by using "->", but not if you need an actual pointer to the data. For that, you can use "&*ptr".

It is useful for:

  • Objects that must be allocated with new, but that you'd like to have the same lifetime as something on that stack. If the object is assigned to a smart pointer, then they will be deleted when the program exits that function/block.

  • Data members of classes, so that when the object is deleted all the owned data is deleted as well, without any special code in the destructor (you will need to be sure the destructor is virtual, which is almost always a good thing to do).

You may not want to use a smart pointer when:

  • ... the pointer shouldn't actually own the data... i.e., when you are just using the data, but you want it to survive the function where you are referencing it.
  • ... the smart pointer isn't itself going to be destroyed at some point. You don't want it to sit in memory that never gets destroyed (such as in an object that is dynamically allocated but won't be explicitly deleted).
  • ... two smart pointers might point to the same data. (There are, however, even smarter pointers that will handle that... that is called reference counting.)

See also:

Mark Santesson
+7  A: 

Most kinds of smart pointers handle disposing of the pointer-to object for you. It's very handy because you don't have to think about disposing of objects manually anymore.

The most commonly-used smart pointers are std::tr1::shared_ptr (or boost::shared_ptr), and, less commonly, std::auto_ptr. I recommend regular use of shared_ptr.

shared_ptr is very versatile and deals with a large variety of disposal scenarios, including cases where objects need to be "passed across DLL boundaries" (the common nightmare case if different libcs are used between your code and the DLLs).

Chris Jester-Young
A: 

Check out this question:
Smart Pointers: Or who owns you baby

Martin York
+17  A: 

Smart pointer is a pointer-like type with some additional functionality, e.g. automatic memory deallocation, reference counting etc.

Small intro is available here.

One of the simple smart-pointer type is std::auto_ptr (chapter 20.4.5 of C++ standard), which allows to deallocated memory automatically when it out of scope and which is more robust than simple pointer usage when exceptions are throw, although less flexible.

Another convenient type is boost::shared_ptr which implements reference counting and automatically deallocate memory when no references to object remain, this helps to avoid memory leaks, it is easy to use to implement RAII.

Subject is covered in depth in book "C++ Templates: The Complete Guide" by David Vandevoorde, Nicolai M. Josuttis, chapter Chapter 20. Smart Pointers. Some topics covered:

sergdev
+1 for the intro link.
Lazer
+72  A: 

A smart pointer is a class that wraps a "bare" C++ pointer, to manage the lifetime of the object being pointed to.

With "bare" C++ pointers, the programmer has to explicitly destroy the object when it is no longer useful.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething();// Use the object in some way.
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception....

A smart pointer by comparison defines a policy as to when the object is destroyed. You still have to create the object, but you no longer have to worry about destroying it.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

The simplest policy in use involves the scope of the smart pointer wrapper object, such as implemented by boost::scoped_ptr or std::tr1::scoped_ptr.

void f()
{
    {
       boost::scoped_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // boost:scopted_ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

Note that scoped_ptr instances cannot be copied. This prevents the pointer from being deleted multiple times (incorrectly). You can however pass references to it around to other functions you call.

Scoped pointers are useful when you want to tie the lifetime of the object to a particular block of code, or if you embeded it as member data inside another object, the lifetime of that other object. The object exists until the containing block of code is exitted, or until the containing object is itself destroyed.

A more complex smart pointer policy involves reference counting the pointer. This does allow the pointer to be copied. When the last "reference" to the object is destroyed, the object is deleted. This policy is implemented by boost::shared_ptr and std::tr1:shared_ptr.

void f()
{
    typedef std::tr1::shared_ptr<MyObject> MyObjectPtr; // Nice short alias.
    MyObjectPtr p1; // Empty
    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1=p2; // Copy the pointer.
        // There is are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

Reference counted pointers are very useful when the lifetime of your object is much more complicated, and is not tied directly to a particular section of code or to another object.

There is one drawback to reference counted pointers -- the posibility of creating a dangling reference.

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

Another possibility is creating circular references.

struct Owner {
   boost::shared_ptr<Owner> other;
};

boost::shared_ptr<Owner> p1 (new Owner());
boost::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

To work around this problem, both boost and std::tr1 define weak_ptr to define a weak (uncounted) reference to a shared_ptr.

Also note that the existing standard C++ library does define a special kind of smart pointer std::auto_ptr. It is very much like a scoped pointer, except that it also has the "special" dangerous ability to be copied -- which also unexpectedly transfers ownership!

std::auto_ptr<MyObject> p1 (new Owner());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Uhoh. Hopefully raises some NULL pointer exception.
Lloyd
Holy smokes, this is a good writup.
Stephen Deken
Thanks, Lloyd. This is very helpful!
Alex Reynolds
Should note that auto_ptr will be depreciated in c++0x.
rlbond
very nice. Thanks for the right up.
Derek B.
+4  A: 

Definitions provided Chris,Sergdev and Llyod is correct. I prefer a simpler definition though, just to keep my life simple: Smart pointer is simply a class that overloads -> and * operators. Which means that your object semantically looks like a pointer but you can make it do way cooler things, including reference counting, automatic destruction etc. shared_ptr and auto_ptr are sufficient in most cases, but come along with their own set of small idiosyncrasies..

Sridhar Iyer
+2  A: 

Note that the implementation of std::auto_ptr in Visual Studio 2005 is horribly broken.
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842

Use the boost ones instead.

Richard
A: 

Two excellent articles on the subject:

Lazer