More C++ Idioms/Resource Return
Resource Return
[edit | edit source]Intent
[edit | edit source]To convey ownership transfer (of a resource) explicitly in the return type of a factory function.
Also Known As
[edit | edit source]Motivation
[edit | edit source]Factory functions are often used to create new resources and return them to the caller. A new resource could be raw memory, dynamically allocated object, database cursors/connections, locks and so on. An important question about resources is who owns the resource and who releases it? Many times, interfaces are developed where the caller is implicitly responsible for resource release. If the caller is not aware of this fact or simply forgets to take correct steps, it gives rise to an easy-to-use-incorrectly kind of interface. Following code snippet shows an example.
struct X
{
void foo() {}
};
X * Xfactory() // Resource ownership implicitly transferred to the caller.
{
return new X; // Dynamically allocated instance
}
int main (void)
{
Xfactory()->foo(); // Dynamically allocated instance of X leaks here
}
Resource Return Idiom provides different alternatives to rectify the situation and results into (somewhat) hard-to-use-incorrectly interfaces.
Solution and Sample Code
[edit | edit source]The solution is to wrap the resource in a resource-management smart pointer and return the smart pointer instead of the raw pointers. Simplest form of Resource Return Idiom is shown in the code snippet below.
struct X
{
void foo() {}
};
std::unique_ptr<X> Xfactory() // Resource ownership explicitly transferred to the caller.
{
return std::unique_ptr<X> (new X); // Dynamically allocated instance
}
int main (void)
{
Xfactory()->foo(); // Dynamically allocated instance of X does not leak here
}
There are several issues to be considered while determining the type of resource-management smart pointer to use to return a resource. Possible options are:
std::auto_ptr- boost::shared_ptr / std::shared_ptr (as of C++11)
- std::unique_ptr in C++0x
- User defined Handle/Body idiom
An excellent discussion of pros and cons of choosing one over the other are discussed at length by Scott Meyers in his article The Resource Return Problem. As long as custom deletion functionality (other than plain old delete) is not required, auto_ptrs are a quick way to use the Resource Return idiom as shown above. auto_ptrs give exclusive but transferable ownership of resources which becomes very clear just by looking at the interface. For dynamically allocated pointer-returning factory functions, boost::shared_ptr is a also good choice because it offers normal copy-semantics (e.g., it can be stored in STL containers). It also allows changes to resource release policy from normal delete operation to custom deletion without disturbing clients.
When exclusive ownership is involved in case of Resource Return idiom, Move Constructor idiom is often useful while transferring ownership of resources.