Any C++ class that overrides the -> operator can be used as a pointer. Smart pointers are usually used to automatically manage the lifetime of the object that they point to using the ResourceAcquisitionIsInitialization idiom. This is necessary to make code exception-safe: in robust C++ code there should (almost) never be raw pointers to dynamically allocated objects on the stack because those objects will not get deleted if an exception unwinds the stack.
The -> operator of a SmartPointer must return a pointer or another object that also has the -> operator. Thus, smart pointers can be "chained" by returning temporary smart pointers that do clever things in their constructor or destructor. For example, a smart pointer could return a chained smart pointer that locks/unlocks a mutex on the pointed-to object.
Smart pointers should also implement the * operator to return a reference to the pointee, in the same manner as built in pointers. However, this is not enforced by the language. Misuse of this feature can make code difficult to understand.
Known uses:
Does anyone know why this is not provided by the standard library? I think it should be.
It turns out the semantics are hard to get Right(TM). And you need still 'dumb' pointers sometimes, so you can't just mandate only smart pointers. I think the comittee punted on this one.
One of the CeePlusPlusIdioms
You can find some smart pointer implementations at http://www.boost.org
See also CppCountedPointerImplementation
Could someone tell me why a SmartPointer does not violate KeepItSimple?
I agree that the convenience is desirable but it seems that this comes at the expense of additional complexity. There doesn't seem to be much simplicity about it. Even the author above admits that some of the finer implementation details of SmartPointers can make code difficult to understand.
Although smart pointers themselves can be somewhat complex to design and implement, using them is usually very easy, and in fact simplifies a lot of code. The most common use of smart pointers is management of object lifetimes, which can be very hard to get right in some contexts. Choosing an appropriate smart pointer can make this management almost completely transparent. As usual, you pay with complexity in a low-level library utility in order to gain simplicity and ease-of-use in application code. It has always seemed like a good trade-off to me.
BTW, the phrase you quoted was almost certainly intended to apply to unconventional implementations of operator*, rather than to smart pointers in general. Overloading any operator with unusual semantics is invariably confusing and should be avoided. -- DanMuller
[Thanks for your reply - I've clarified my question above to remove the misquote.]
Use of smart pointers generally does simplify code. A problem arises if you have lots of different kinds of smart pointers with different semantics. For example, if you are writing a C++ application that uses ATL COM objects and CORBA, things can get confusing as you try to remember all the rules for all the pointer types. But it's still easier than using raw pointers.
It's important to remember that every SmartPointer implementation you run into is going to be different from the ones you've seen before, and you need to investigate the subtleties.
(Years later...)
I worked extensively with C++ for about a decade, and saw first-hand how disciplined use of smart pointers in a large C++ program gradually all but eliminated the kinds of memory management problems that plague C programs. In addition, due to the deterministic timing of object destruction in C++, the management of other kinds of resources was also eased. Now I've also worked for several years intensively with C#, and seen how dynamic memory management helps with the former, and helps not at all with the latter, leading to the introduction of mechanisms (IDispose) that are similar to C++-style smart pointers for scope-based resource management. Having again worked with C++ for the past few months, I find that the C++ approach is still appealing.
Specifically, the choice of a smart pointer type is a succinct form of documentation. Use of auto_ptr indicates sole ownership, so that when reading existing code, you know immediately that aliasing of the reference object is unlikely, and you can see fairly clearly when ownership is transferred. In C# programs, I've often had great difficulty tracking down all the concurrent references to a given object in a (sometimes needlessly) complex program. If the object is mutable, being aware of these multiple references is critical to understanding runtime behavior.
-- DanMuller