Use RAII objects such as tr1::shared_ptr
and auto_ptr
to prevent resource leaks.
First of all, let’s make clear the concept: a resource is something that we need to return to the system once we’re done using it, such as dynamically allocated memory, file descriptors, mutex locks, fonts and brushes in graphical user interfaces (GUIs), database connections, and network sockets.
The motivation of using objects to manage resources is that, it is hard to write manually managed code to deal with complex control flow where necessary resource handling operation such as delete
may have to be skipped due to premature continue
statement or unexpected exception, ending up with resource leak.
On the other hand, by putting resources inside objects, we can rely on C++’s automatic destructor invocation to make sure that the resources are released properly. Luckily, there’re two kinds of smart pointer that is ideal for this kind of situation:
std::auto_ptr
: destructor automatically callsdelete
on what it points to when theauto_ptr
is destroyed. There’s only oneauto_ptr
pointing to the underlying resoures each timestd::tr1::shared_ptr
: is areference-counting smart pointer (RCSP)
. Similar to garbage collection but can’t break cycles of references (e.g.: two otherwise unused objects pointing to one another).
1. auto_ptr
We can use auto_ptr
to manage a class Investment
that comes with a factory function (item 7) without worrying about resource leak:
|
|
There are two critical aspects worth noting:
- Resources are acquired and immediately turned over to resource-managing objects. It is a common trick to acquire a resource and initialize a resource-managing object in the same statement, which is called Resource Acquisition Is Initialization (RAII).
- Resource-managing objects use their destructors to ensure that resources are released. Things could be tricky when the act of releasing resources can lead to exceptions being thrown, which is the matter addressed in Item 8.
Pay attention to the limitation of auto_ptr
: its sole ownership of the resource policy requires that copying auto_ptr
s via copy constructor or copy assignment operator sets them to null:
|
|
2. shared_ptr
An alternative RAII object, shared_ptr
, is an RCSP(reference-counting smart pointer), which is a smart pointer that keeps track of how many objects point to a particular resource and automatically deletes the resource when nobody is pointing to it any longer. The code above is almost the same as with shared_ptr
, but copying behavior is much more natural:
|
|
There is more information on tr1::shared_ptr
in item 14, item 18, and item 54. For now, another point worth noting is that, since both auto_ptr
and tr1::shared_ptr
use delete
in their destructors rather than delete []
(item 16), it is a bad idea to wrap dynamically allocated arrays with auto_ptr
or tr1::shared_ptr
:
|
|
Since having createInvestment
returning a raw pointer type is error-prone, we’ll see in item 18 that an interface modification is preferred.