My program fails due to addition of a pointer to a vector. After much reading and deleting I have changed it to an addition of a shared pointer into a set (using insert) which was fine at first but now fails as well. I tried two solutions; neither worked. One failed as well and the other, the make shared kind, did not compile.
Reading a bit more I came upon this forum which states, that I shouldn’t point to something with two different shared pointers but rather create a copy of it. So what is the big difference of the shared pointer…?
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 theauto_ptrinstance is the entity that will cause that pointer’s destruction. Thanks to hackery, copying anauto_ptractually transfers ownership from the copied object to the object being copied to (note: never do this).So, if you have this:
This is guaranteed to be destroyed (so long as the entity holding it is properly cleaned up). When
p1falls off the stack, the pointer will be destroyed. Ifp1were 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 calledboost::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:
The
auto_ptr::get()function returns the pointer, so this is legal C++ code (it compiles). However, bothp1andp2now think that they own the pointer. Becauseauto_ptronly models single-ownership, that is not allowed. Whenp2is destroyed, it will delete the pointer. Then, whenp1is 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 ashared_ptrto the same object, that object will not be deleted until all three that contain theshared_ptrare deleted.It is important to understand that
shared_ptris 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?
Nope. This is still wrong. The difference between
auto_ptrandshared_ptris that you can do this withshared_ptr:That’s copy construction of
p2fromp1. There is a fundamental difference between creating ashared_ptrfrom a naked pointer and creating one from an already existingshared_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 ashared_from_thisprivate member that member functions of the class can use to transfer ownership around. So:Other than that, you’ll have to transfer ownership by explicitly copying the object around.