How do shared pointers know how many pointers point to that object? (shared_ptr, in this case)
I generally agree with James McNellis's answer. However there's one more point that should be mentioned.
As you may know, shared_ptr may also be used when the type T is not fully defined.
That is:
class AbraCadabra;
boost::shared_ptr myPtr;
// ...
This will compile & work. Unlike many other implementations of smart pointers, which actually demand the encapsulated type to be fully defined in order to use them. This is related to the fact that the smart pointer is supposed to know to delete the encapsulated object when it's no more referenced, and in order to delete an object one must know what it is.
This is achieved by the following trick: shared_ptr actually consists of the following:
The above factory is a helper object with a single virtual function, which is supposed to delete your object in a correct way.
This factory is actually created when you assign a value to your shared pointer.
That is, the following code
AbraCadabra* pObj = /* get it from somewhere */;
myPtr.reset(pObj);
This is where this factory is allocated.
Note: the reset function is actually a template function. It actually creates the factory for the specified type (type of the object passed as a parameter).
This is where your type should be fully defined. That is, if it's still not defined - you'll get a compilation error.
Note also: if you actually create an object of a derived type (derived from AbraCadabra), and assign it to the shared_ptr - it will be deleted in a correct way even if your destructor is not virtual.
The shared_ptr will always delete the object according to the type that is sees in reset function.
So that shared_ptr is a pretty sophisticated variant of a smart pointer. It gives an awesome flexibility. However you should know that this flexibility comes at a price of an extremely bad performance compared to other possible implementations of the smart pointer.
On the other hand - there're so-called "intrusive" smart pointers. They don't have all that flexibility, however in contrast they give the best performance.
Pros of shared_ptr compared to inrusive smart pointers:
shared_ptr. This is very valuable for big projects, reduces dependencies greatly.Cons of shared_ptr compared to inrusive smart pointers:
reset. When one shared_ptr is assigned to another one - nothing more is allocated.shared_ptr you may not mix with raw pointers. AbraCadabra* pObj = /* get it from somewhere */;
myPtr.reset(pObj);
// ...
pObj = myPtr.get();
boost::shared_ptr myPtr2(pObj); // oops
The above will crash.