Failure to do this can lead to subtle resource leaks when exceptions are thrown.
Suppose there’re two functions:
|
|
Apparently, following code won’t compile:
|
|
This is because tr1::shared_ptr’s constructor taking a raw is explicit, there’s no implicit conversion from the raw pointer (returned by new Widget) to the tr1::shared_ptr (required by processWidget).
However, even though the code below does compile, seems correct, and carefully uses shared_ptr to manage resource, it may still leak resources:
|
|
The two arguments as function parameters must be evaluated before a call to processWidget is generated, and the first argument actually consists of two parts:
- execution of the expression
new Widget - call to the
tr1::shared_ptrconstructor
Thus, before processWidget can be called, following three steps must take place:
- Call
priority - Execute
new Widget - Call the
tr1::shared_ptrconstructor
Unlike Java and C#, where function parameters are always evaluated in a particular order, C++ compilers are free to decide the order of steps above. Although new Widget must take place before tr1::shared_ptr constructor can be call (for the result of new operation is the argument of the smart pointer’s constructor), the call to priority() can be performed first, second, or third. If compilers choose to perform it second (maybe for efficiency consideration):
- Execute
new Widget - Call
priority - Call
tr1::shared_ptrconstructor
The problem here is that, once the call to priority yields an exception, the pointer returned from new Widget has not turned over to the resource-managing object, and resource leaks.
Luckily, it is very simple to avoid this problem: use a separate statement to create Widget and store it in a smart pointer, then pass the smart pointer to processWidget:
|
|
Now the new Widget expression and the call to tr1::shared_ptr constructor are in a different statement from the call to priority, compilers are not allowed to move the call to priority between them.