I recently started learning about smart pointers and move semantics in C . But I can't figure out why this code works. I have such code:
#include <iostream>
#include <memory>
using namespace std;
class Test
{
public:
Test()
{
cout << "Object created" << endl;
}
void testMethod()
{
cout << "Object existing" << endl;
}
~Test()
{
cout << "Object destroyed" << endl;
}
};
int main(int argc, char *argv[])
{
Test* testPtr = new Test{};
{
unique_ptr<Test> testSmartPtr(testPtr);
}
testPtr->testMethod();
return 0;
}
My output is:
Object created
Object destroyed
Object existing
Why does row testPtr->testMethod()
work? Doesn't unique_ptr delete the pointer assigned to it on destruction if the pointer is an lvalue?
Edit: I learned from the comments that this method doesn't check if the pointer exists. If so, is there a way to check if the pointer is valid?
Edit: I learned that I shouldn't do anything with invalid pointers. Thank you for all your answers and comments.
CodePudding user response:
You do not need a std::unique_ptr
to write code with the same issue
int main(int argc, char *argv[])
{
Test* testPtr = new Test{};
delete testPtr;
testPtr->testMethod(); // UNDEFINED !!!
return 0;
}
The output is the same as yours here https://godbolt.org/z/8bocKGj1M, but it could be something else entirely. The code has undefined behavior. You shall not dereference an invalid pointer.
If you had actually used members of the object in testMethod()
some faulty output or a crash is more likely, but also not guaranteed. Looking ok is the worst incarnation of undefined behavior.
Your code demonstrates nicely why you should ban raw new
completely. At least you should call new
only as parameter to the smart pointers constructor, or even better, use std::make_unique
. Its basically just a wrapper around a constructor call via new
and its main purpose is to let you write code that is free of new
:
int main(int argc, char *argv[])
{
auto testPtr = std::make_unique<Test>();
testPtr->testMethod();
return 0;
}
Even then you can access the raw pointer and do wrong stuff. Smart pointers help with ownership, but they are not fool-proof.