Smart Pointers
To use dynamic binding in C++, you must use pointers or references, because virtual functions work only in the context of a base-class pointer (or reference) that points (or refers) to a derived-class object.
However, neither pointers nor references do anything about memory allocation. As a result, C++ programmers who wish to use dynamic binding take on a memory-allocation burden that the language does nothing directly to solve.
The C++0x library adds three template classes that combine pointer-like behavior with automatic memory allocation in various ways: shared_ptr, unique_ptr, and weak_ptr. We expect that shared_ptr will be the most common; it is typically used this way:
class B { /* ... */ };
class D: public B { /* ... */ };
shared_ptr<B> pb(new D);
We have defined two classes related by inheritance. Now, we allocate a derived-class object, and instead of using a pointer variable to remember the pointer resulting from new, we use that pointer to initialize a shared_ptr<B>. From this point on, there is no need to use raw pointers directly.
From a user's viewpoint, a shared_ptr<B>' object is a value that acts like a pointer to an object of type B or of a type derived from B. You can copy shared_ptr objects freely; all copies refer to the same object. If pb is a shared_pointer<B> and mem is a member of B, you can refer to pb->mem as if pb were a pointer; if pb->mem is a virtual function, you can call it in the same way.
Where a shared_ptr differs from an ordinary pointer is that it keeps track of how many shared_ptr objects point to each individual object. When all of the shared_ptr objects pointing to a particular object go away, that object is destroyed too. Therefore, when you use new to allocate an object and give that object to a shared_ptr to manage, you don't have to worry about writing a delete to match your new.
Not having to worry about delete is a bigger deal than it seems at first. For example, it means that if you have a function that has a shared_ptr as a local variable, and there is no other copy of that shared_ptr, the object to which that shared_ptr refers will go away automatically when the function returns. Moreover, shared_ptrs behave this way even if the function returns due to an exception. In effect, shared_ptrs make exception-safe programs much easier to write.
They also make destructors unnecessary in many cases. If a class uses new in its constructors, all it has to do is use those calls to new to initialize shared_ptr data members; and the need for a delete in the destructor goes away. If that's all the destructor does — which is often the case — the whole destructor vanishes. Not only that, but without a user-defined destructor, a class can often do without a user-defined copy constructor or copy-assignment operator as well.
As a result, by using shared_ptr, class authors can often reduce the burden of writing four special member functions (constructor, destructor, copy constructor, and copy-assignment operator) to one (constructor). From a teaching viewpoint, using shared_ptr makes it possible to introduce constructors much earlier in the curriculum without having to introduce the other three special members until later.
In addition to shared_ptr, C++0x offers unique_ptr, which can be moved but not copied. This property means that only a single unique_ptr points to a given object at one time. If you can accept the no-copy restriction, unique_ptr runs more quickly than shared_ptr.
C++0x also offers weak_ptr, which is like shared_ptr except that it never deletes anything. Instead, when a weak_ptr points to the same object as a shared_ptr, and the last copy of the shared_ptr goes away (thereby deleting the object), the weak_ptr makes note of the deletion and lets you test later to see if this deletion has occurred. The main use of weak_ptr is to define circular data structures, which would otherwise never go away.


