I stumbled upon code like this:
void foo(T* bar); // Note: takes ownership of 'bar'.
foo(new T());
And now I wonder if there is any point in refactoring it to:
void foo(T* bar); // Note: takes ownership of 'bar'.
auto tempT = std::make_unique<T>();
foo(tempT.release());
- Is it more exception-safe?
- It certainly adds a little bit more clarity regarding the transfer of ownership, though calling 'new' from the argument list already makes that very clear by itself.
Note that I unfortunately can't change the signature of 'foo'.
CodePudding user response:
Is it more exception-safe?
No. However, consider a slightly more complex example:
auto tempT = std::make_unique<T>();
some_operation();
foo(tempT.release());
In this case, there would be a potential issue with exception safety if unique_ptr wasn't used.
That said, much safer would be:
void foo(std::unique_ptr<T> bar); // no need to note that takes ownership
// because that's implied by the type
Note that I unfortunately can't change the signature of 'foo'.
Then write a wrapper function that you can control.
CodePudding user response:
No it is not more exception safe.
But consider if function changes to take more parameters:
void foo(T* bar, T* more_bar = get_more_bar()); // Note: takes ownership of both.
foo(new T());
Now what if get_more_bar()
is evaluated after new T()
and throws.
CodePudding user response:
You might consider writing a wrapper for foo:
void wrap_foo(std::unique_ptr<T> arg) {
foo(arg.get());
arg.release();
}
If foo were to throw an exception without freeing the memory, this would free it. However, if foo is already exception-safe and frees the memory before it throws an exception, this would free it twice. Unfortuately there's no good way to write a safe wrapper for this that will detect if the memory has been released properly or not.