Smart Pointers

It's easy to simply forget to release allocated memory, and doing so can involve some work. The destructor helps with the remembering, but it does not apply in all circumstances.

To create an automated solution, the system must have some way to know when allocated objects are no longer in use. A system which provides a general garbage collections, just as Java, must solve an expensive graph problem to find this out. That's what makes GC expensive.

As noted above, C++ provides a bit of optional garbage collection through smart pointers. These are partial solutions, since they work only in limited circumstances. There are two kinds, for each of which we will look at examples below.

Shared Pointer

The shared_ptr uses reference counting. In that system, each allocated block contains, hidden from the user, a count of how many pointers there are to it. Whenever a pointer is copied, the count is incremented. When one is destroyed, the count is decremented. When the count reaches zero, the allocated object is deleted. This is accomplished automatically semantics of assignment and copying to perform all needed updates, and the conditional delete. This adds overhead to any operation which changes a shared_ptr variable.

The solution is partial, because it may fail for cyclical structures: loops or double-linked lists. To see this, consider the simplest case of allocating a node which points to itself. It will not be deleted even if there are not other pointer to it. A general GC system will not fail in this way. It is legitimate to create a linked structure using shared_ptr, but you may still need to take action to cause it to be deleted. Setting to null enough pointers to break all cycles is sufficient, and shared_ptr will do the rest.

Unique Pointer

The unique_ptr uses the compiler type system to assure that, at any time, at most one pointer to any allocated block may exist. Whenever any non-null pointer is destroyed, the block it pointed to can be deleted, since no other pointers exist. This condition is guaranteed using the system type rules. You are forbidden from copying or assigning unique_ptr objects, except to assign the null pointer. A special utility is provided to move a pointer value from one variable to another, leaving the source null, without ever creating multiple copies. This makes unique_ptr harder to use, but by enforcing the rules at compile time, it avoids creating runtime overhead.

The unique_ptr is a limited solution since it essentially forbids the construction of cyclic structures. Any double-linked structure involves two pointers to most nodes. Even a singly-linked ring would be impossible to close.

C++ does not provide general garbage collection, but instead provides two limited forms of it. These are more efficient, and cover most of what a programmer will actually do. But you do need to be aware of how they work to use them effectively.