Reputation: 351
I wrote accidentally a statement like
std::unique_ptr<Thing> m_thing;
m_thing->DoStuff();
instead of
std::unique_ptr<Thing> m_thing(new Thing);
m_thing->DoStuff();
the first example compiles and run, which doesn't make any sense to me because m_thing is not pointing to any object. Here a slightly bigger code example.
#include <iostream>
#include <memory>
class Thing
{
public:
~Thing(){ std::cout << "destructor of class Thing\n"; }
void DoStuff(){ std::cout << "doing stuff\n"; }
};
void Foo()
{
std::unique_ptr<Thing> m_thing;
m_thing->DoStuff(); //why does this work, since i suppose m_thing to be empty?
}
int main()
{
Foo();
std::cout << "after Foo()\n";
std::cin.get();
return 0;
}
Why can the "empty" m_thing unique_ptr invoke the DoStuff()-Method of the Thing-class? i noticed also, that the destructor of Thing-class never gets invoked when declaring m_thing with
std::unique_ptr<Thing> m_thing;
instead of
std::unique_ptr<Thing> m_thing(new Thing);
I didn't found any explanation of this behaviour via google, so i hope maybe someone can explain to me what is happening here behind the curtains.
Upvotes: 1
Views: 1480
Reputation: 52471
Your program exhibits undefined behavior. "Seems to work" is one possible manifestation of undefined behavior. It's morally equivalent to
Thing* p = NULL;
p->DoStuff();
which I predict would also compile and run. DoStuff
is called with NULL
for this
pointer - but it doesn't actually use this
, that's why it doesn't crash and burn as you expect.
Upvotes: 4
Reputation: 15673
DoStuff
isn't virtual and doesn't access any members of your object, so you can get away with calling it (I'm pretty sure this is unspecified behavior though). The default constructor for unique_ptr
initializes it to nullptr
, so it doesn't allocate any memory on its own.
Oh, and the destructor of course doesn't get called because unique_ptr doesn't invoke its deleter on nullptr
s.
Upvotes: 4