It's all about ownership. An entity (a function or object) is said to "own" a pointer if it is that entity's job to ensure that the pointer is deleted. Any time you use new, someone, somewhere must take ownership of the pointer returned. If this is not the case, you have a memory leak.
The purpose of all kinds of smart pointers is to model some form of ownership. The destructor of the smart pointer is what can trigger the deletion of the pointer.
std::auto_ptr (as long as you don't copy it) models single-ownership. That is, whatever entity has the auto_ptr instance is the entity that will cause that pointer's destruction. Thanks to hackery, copying an auto_ptr actually transfers ownership from the copied object to the object being copied to (note: never do this).
So, if you have this:
std::auto_ptr<int> p1 = new int(4);
This is guaranteed to be destroyed (so long as the entity holding it is properly cleaned up). When p1 falls off the stack, the pointer will be destroyed. If p1 were a member of a class, then the pointer will be destroyed when that class instance is destroyed. The lifetime of the pointer is scoped. Boost actually has a non-copyable equivalent called boost::scoped_ptr.
There are several rules that you must abide by when using any kind of smart pointers. This is the most important.
Rule #1: If you construct a smart pointer instance from a naked pointer, what you are saying is, "No object currently has ownership of this pointer. I am now giving ownership to you, the smart pointer." That is what it means to construct a smart pointer object from a naked pointer.
This code is a violation of Rule #1:
std::auto_ptr<int> p1 = new int(4); std::auto_ptr<int> p2 = p1.get();
The auto_ptr::get() function returns the pointer, so this is legal C++ code (it compiles). However, both p1 and p2 now think that they own the pointer. Because auto_ptr only models single-ownership, that is not allowed. When p2 is destroyed, it will delete the pointer. Then, when p1 is destroyed, it will try to delete the same pointer.
Oops.
Now that we're all very clear on Rule #1, let's look at shared_ptr. This smart pointer models shared ownership. Multiple entities can claim ownership of the pointer at the same time. The pointer will only be deleted when all of them are finished using it. So if 3 objects all contain a shared_ptr to the same object, that object will not be deleted until all three that contain the shared_ptr are deleted.
It is important to understand that shared_ptr is a smart pointer. And therefore, it is subject to Rule #1.
That may not make sense. After all, it's supposed to allow shared ownership. That must mean that this is allowable, right?
shared_ptr<int> p1 = new int(4); shared_ptr<int> p2 = p1.get();
Nope. This is still wrong. The difference between auto_ptr and shared_ptr is that you can do this with shared_ptr:
shared_ptr<int> p1 = new int(4); shared_ptr<int> p2 = p1;
That's copy construction of p2 from p1. There is a fundamental difference between creating a shared_ptr from a naked pointer and creating one from an already existing shared_ptr. The latter is what actually shares ownership between the two. The former will just cause badness.
Therefore, if you ever have a naked pointer and put it in a shared_ptr, you can only do this for that pointer one time. If you want to share ownership, you must copy it around.
There is one semi-backdoor: enable_shared_from_this. If you derive a class from this type, then your class will have a shared_from_this private member that member functions of the class can use to transfer ownership around. So:
struct Type : public enable_shared_from_this { DoSomething() { shared_ptr<Type> p2 = shared_from_this(); FunctionThatTakesOwnership(p2); } }; shared_ptr<Type> p1 = new Type; p1->DoSomething();
Other than that, you'll have to transfer ownership by explicitly copying the object around.