I have a method that returns an object by value. The method comes from a library that I have no control over. For the further handling of the object I want to continue working with a unique_ptr on this object. Here is an example:
#include <iostream>
#include <memory>
class Bla {
public:
Bla() { std::cout << "Constructor!\n"; }
~Bla() { std::cout << "Destructor!\n"; }
};
Bla GetBla() {
Bla bla;
return std::move(bla);
}
int main() {
auto bla = std::make_unique<Bla>(GetBla());
}
The example produces the following output:
Constructor!
Destructor!
Destructor!
Destructor!
Why is the destructor of Bla called 3 times here? Is the way I create the unique_prt correct?
There are indeed 3 times that an instance of Bla
is constructed.
Bla GetBla() {
Bla bla; // 1st construction
return std::move(bla); // 2nd construction (return by copy)
}
Don't return by move. Just return bla
, in most cases the copy will be elided.
auto bla = std::make_unique<Bla>(GetBla()); // 3rd construction - Bla copy construction
Note that make_unique<Bla>
always constructs a new instance. In this case because you're passing another instance, it becomes copy-construction.
A hint that copy construction takes place is that your default constructor is invoked only once, while the destructor is invoked 3 times. That's because in the other 2 cases the implicit copy (or move) constructor is invoked (Bla::Bla(Bla const&)
).
The compiler may even warn you that
moving a local object in a return statement prevents copy elision.
I'm not 100% sure, but I think you get the three desctructor calls from:
bla
from GetBla()
GetBla()
after it was used in std::make_unique<Bla>(GetBla());
std::unique_ptr
The easiest way is to let std::make_uniqe
invoke the default constructor of Bla
:
auto bla = std::make_unique<Bla>(); // Calls Bla::Bla() to initalize the owned object
#include <iostream>
#include <memory>
class Bla {
public:
Bla() { std::cout << "Constructor!\n"; }
~Bla() { std::cout << "Destructor!\n"; }
};
int main() {
auto bla = std::make_unique<Bla>();
}
Output
Constructor!
Destructor!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With