问题
TLDR
Why does the line t_ptr = std::unique_ptr<Test>(t_ptr.get()); cause the destructor to be called?
The line seems to just innocently assign t_ptr back to itself...
Further, why am I able to continue calling methods after the supposed destruction?
Example Code
class Test
{
public:
Test()
{
printf("Constructor called: %p\n", this);
i = 0;
};
void print()
{
printf("%d\n", i++);
};
~Test()
{
printf("Destructor called: %p\n", this);
};
private:
int i;
};
int main(int argc, char** argv)
{
std::unique_ptr<Test> t_ptr = std::unique_ptr<Test>(new Test());
t_ptr->print();
t_ptr->print();
t_ptr->print();
t_ptr = std::unique_ptr<Test>(t_ptr.get());
t_ptr->print();
t_ptr->print();
t_ptr->print();
};
The output is
Constructor called: 0x55c9811a1e70
0
1
2
Destructor called: 0x55c9811a1e70
0
1
2
Destructor called: 0x55c9811a1e70
回答1:
Why does the line
t_ptr = std::unique_ptr<Test>(t_ptr.get());cause the destructor to be called?
Because unique_ptr needs to delete the currently held object when assigning it a new one. Otherwise it would leak the current object. However, it will not check whether the new one is actually the same as the current one. If you do that, the behavior is undefined.
Further, why am I able to continue calling methods after the supposed destruction?
Because this is undefined behavior. You are calling functions on an object that has been deleted. What happens when you do that is undefined. On your system it works, on mine it crashes.
(Off-topic side note)
I recommend getting into the habit of never using new if you can avoid it, and using std::make_unique (or std::make_shared for shared_ptr) instead:
auto t_ptr = std::make_unique<Test>();
There's benefits with exception safety in some cases when the constructor throws. Basically, as of 2019 at least, the current rule of thumb is "do not use new or delete."
来源:https://stackoverflow.com/questions/55627418/why-does-reassigning-a-smart-pointer-to-itself-cause-destruction