Consider the code
struct Resource
{
Resource()
{
std::cout << "C";
}
~Resource()
{
std::cout << "D";
}
};
void allocate(Resource **p)
{
*p = new Resource();
}
int main()
{
Resource *p = nullptr;
allocate(&p);
std::unique_ptr<Resource> uptr(p);
//stuff
}
Assuming that 'allocate' function is heavily used in legacy code in multiple call sites, the main function shows an attempt to use unique_ptr to manage the allocated resource. The problem occurs when another programmer on the team writes exception prone code after 'allocate' and before 'unique_ptr' gets to own it.
So, one solution that comes to my mind is to write code which leverages the comma operator as follows
std::unique_ptr<Resource> up((allocate(&p), p));
Is there another reasonable way to handle this situation? Basic problem is to make alllocation and ownership as an atomic operation.
3 Answers 3
For the smoothest transition, create an overload of allocate:
template <typename T>
void allocate(std::unique_ptr<T>* p) {
T* raw;
allocate(&raw)
p->reset(raw);
}
Existing call sites will continue to work unchanged. When you update a call site, you replace the raw pointer with a unique_ptr, and remove whatever line frees the resource, but otherwise keep the code unchanged. (Replace places where the raw pointer is passed with .get().)
The typical way to do that is to return a unique_ptr from an overloaded function:
std::unique_ptr<Resource> allocate()
{
return std::unique_ptr<Resource>(new Resource());
}
4 Comments
unique_ptr constructor called automatically?Frankly, I rather like your comma solution. Of course, you still need your forgetful exception-happy programmers to remember to use it, so it doesn't work as a catch-all fix.
In fact, on that basis, there isn't one.
Resource *allocate() { Resource *result; allocate(&result); return result; }, and then use that function:std::unique_ptr<Resource> up(allocate());Is your real problem more general, and if so, can you edit your question to include cases that cannot be solved like that?allocatefunction such that, it'll return a movedstd::unique_ptr?