C++ is all about memory ownership
Aka "Ownership Semantics"
It is the responsibility of the owner of a chunk of dynamically allocated memory to release that memory. So the question really becomes who owns the memory.
In C++ ownership is documented by the type a RAW pointer is wrapped inside thus in a good (IMO) C++ program it is very rare [RARE not NEVER] to see RAW pointers passed around (as RAW pointers have no inferred ownership thus we can not tell who owns the memory and thus without careful reading of the documentation you can't tell who is responsible for ownership).
Conversely it is rare to see RAW pointers stored in a class each RAW pointer is stored within its own SMART pointer wrapper. (N.B.: If you don't own an object you should not be storing it because you can not know when it will go out of scope and be destroyed.)
So the question:
- What type of Ownership Semantic have people come across?
- What standard classes are used to implement those semantics?
- What situations do you find them useful?
Lets keep 1 type of semantic ownership per answer so they can be voted up and down individually
Summary:
Conceptually smart pointers are simple and a naive implementations are easy. I have seen many attempted implementations, but invariably they are broken in some way that is not obvious to casual use and examples. Thus I recommend always using well tested "Smart Pointers" from a library rather than rolling your own. std::auto_ptr or one of the boost smart pointers seem to cover all my needs.
std::auto_ptr<T>:
Single person owns the object.
But transfer of ownership is allowed.
Usage:
======
This allows you to define interfaces that show the explicit transfer of ownership.
boost::scoped_ptr<T>
Single person owns the object.
Transfer of ownership is NOT allowed.
Usage:
======
Used to show explicit ownership.
Object will be destroyed by destructor or when explicitly reset.
boost::shared_ptr<T> (std::tr1::shared_ptr<T>)
Multiple ownership.
This is a simple reference counted pointer. When reference count reaches zero object is destroyed.
Usage:
======
When object can have multiple owers with a lifetime that can not be determined at compile time.
boost::weak_ptr<T>
Used with shared_ptr<T>.
In situations where a cycle of pointers may happen.
Usage:
======
Used to stop cycles from retaining objects when only the cycle is maintaining a shared refcount.
yasper::ptr is a lightweight, boost::shared_ptr like alternative. It works well in my (for now) small project.
In the web page at http://yasper.sourceforge.net/ it's described as follows:
For me, these 3 kinds cover most of my needs:
shared_ptr
- reference-counted, deallocation when the counter reaches zeroweak_ptr
- same as above, but it's a 'slave' for ashared_ptr
, can't deallocateauto_ptr
- when the creation and deallocation happen inside the same function, or when the object has to be considered one-owner-only ever. When you assign one pointer to another, the second 'steals' the object from the first.I have my own implementation for these, but they are also available in
Boost
.I still pass objects by reference (
const
whenever possible), in this case the called method must assume the object is alive only during the time of call.There's another kind of pointer that I use that I call hub_ptr. It's when you have an object that must be accessible from objects nested in it (usually as a virtual base class). This could be solved by passing a
weak_ptr
to them, but it doesn't have ashared_ptr
to itself. As it knows these objects wouldn't live longer than him, it passes a hub_ptr to them (it's just a template wrapper to a regular pointer).When a resource is shared between multiple objects. The boost shared_ptr uses reference counting to make sure the resource is de-allocated when everybody is finsihed.
There is another frequently used form of single-transferable-owner, and it is preferable to
auto_ptr
because it avoids the problems caused byauto_ptr
's insane corruption of assignment semantics.I speak of none other than
swap
. Any type with a suitableswap
function can be conceived of as a smart reference to some content, which it owns until such time as ownership is transferred to another instance of the same type, by swapping them. Each instance retains its identity but gets bound to new content. It's like a safely rebindable reference.(It's a smart reference rather than a smart pointer because you don't have to explicitly dereference it to get at the content.)
This means that auto_ptr becomes less necessary - it's only needed to fill the gaps where types don't have a good
swap
function. But all std containers do.When you need to allocate memory dynamically but want to be sure it gets deallocated on every exit point of the block.
I find this usefull as it can easily be reseated, and released without ever having to worry about a leak
From boost, there's also the pointer container library. These are a bit more efficient and easier to use than a standard container of smart pointers, if you'll only be using the objects in the context of their container.
On Windows, there are the COM pointers (IUnknown, IDispatch, and friends), and various smart pointers for handling them (e.g. the ATL's CComPtr and the smart pointers auto-generated by the "import" statement in Visual Studio based on the _com_ptr class).