Consider the following code:
#include <memory>
#include <iostream>
#include <string>
struct Data {
std::string name;
Data(std::string aName): name(aName) {
std::cout << name << " Constructor is called\n";
}
~Data() {
std::cout << name << " Destructor is called \n";
}
};
int main() {
std::unique_ptr<Data> ptr1(new Data("Data1"));
std::unique_ptr<Data> ptr2(new Data("Data2"));
// Will this always call the destructor of the object owned by ptr2 ?
ptr2 = std::move(ptr1);
return 0;
}
Wil the line ptr2 = std::move(ptr1) always call the destructor of the previously owned object of ptr2? If this is true, can we replace the code below:
std::unique_ptr<Data> ptr1(new Data("Data1"));
ptr2 = std::move(ptr1);
with
ptr2.reset(new Data("Data1"));
?
I tried searching in cpp reference doc and the similar questions in other forums, but I could not get a clarity on this.
Link to godbolt : https://godbolt.org/z/cYhKMWdsT
For demonstration, I extended your example a bit and added a simple wrapper around unique_ptr:
This produces the following output:
(https://godbolt.org/z/nnK11nfq3)
As you can see, the moment that ptr2 is reassigned, Data2 is destructed, because the unique pointer that contained it is reassigned. (It's move assignment operator is called, which calls
deleteon the previously contained object).The final result will be equivalent to the
resetalternative you propose.It is worth noting that this is in fact a consequence of the move assignment operator being called, not
std::move, which simply reinterprets the type of the reference as an rvalue reference, but otherwise has no side effects.