Reputation: 11904
I want to do something like this:
unique_ptr<MyObj> MyFunc() {
MyObj* ptr = new MyObj();
...
return unique_ptr<MyObj>(ptr);
}
unique_ptr<MyObj> value = MyFunc();
But I'm unsure if the object will be deleted when the temporary value was destructed after the function returns. If so, how should I implement correctly a function that returns a unique_ptr
?
Upvotes: 5
Views: 2005
Reputation: 62563
No, the object will not be deleted when function scope ends. This is because move constructor of unique_ptr
will 'move' the ownership semantics to the new unique_ptr
object, and destruction of the old unique_ptr
will not cause deletion of the allocated object.
Note: This is not the right way of doing this. If there is an exception thrown between the point of memory allocation and unique_ptr<>
creation you will have a memory leak.
Upvotes: 10
Reputation: 2987
If nothing goes wrong, your code should work; the original object will be created within the MyFunc
function and its ownership will be transferred back to the caller. However, the best way to create a std::unique_ptr
is with std::create_unique
(to avoid possible leaks upon intervening error conditions). You can verify that this happens correctly with either a debugger or some console output; My expansion/modification of your code (shown below) produces the following output, verifying that only one object is created and it is destroyed at the end of main
):
Created
999
Destroyed
Here's the code:
#include <iostream>
#include <memory>
class MyObj
{
public:
MyObj( int v )
: value( v )
{
std::cout << "Created" << std::endl;
}
~MyObj()
{
std::cout << "Destroyed" << std::endl;
}
int value;
};
std::unique_ptr<MyObj> MyFunc()
{
auto ptr = std::make_unique<MyObj>( 999 );
// ...do other stuff here?...
// return std::move( ptr ); // Loki Astari says move() is unnecessary
return ptr;
}
int main()
{
auto p = MyFunc();
std::cout << p->value << std::endl;
return 0;
}
Upvotes: 0
Reputation: 26476
Although the code can compile and work, it is the best to work with std::make_unique
directly:
return std::make_unique<T>(/* your arguments*/);
your snippet can create some problems such as:
new
can throw std::bad_alloc
if no memory availableMyObj
can throw an exceptionptr
can get lost in the way until it is assigned to the unique_ptr
Upvotes: 3
Reputation: 2518
The way to allocate the pointer is std::make_unique. There are similar functions for the other types of smart pointers as well, e.g. std::make_shared.
If you want to return it from a function, you should use std::move, since unique_ptrs don't like to be copied.
Return it like this: return std::move(ptr);
Upvotes: 1