ttriet204 ttriet204 - 3 months ago 7
C++ Question

method on deleted instance of class still work?

I have this code on Visual C++ 2010

#include <iostream>
#include <string>

using namespace std;

class Human {
private:
int magic;
int health;
string name;
public:
int GetMagic() const;
int GetHealth() const;
Human(int, string);
~Human();

};
//helper
int Human::GetHealth() const {
cout <<"This returns Human::health" << endl;
return Human::health;

}
int Human::GetMagic() const {
cout <<"This returns this->magic"<< endl;
return this->magic;

}

//con/destructor
Human::Human(int a, int b, string c): health(a), magic(b), name(c)
{
cout<<c<<" is born!"<<endl;
}
Human::~Human()
{
cout <<this->name << " is killed!" << endl;
}

int main (){
Human lucife(20,10,"Lucife");
cout << lucife.GetHealth()<<endl;
cout << lucife.GetMagic()<<endl;
lucife.~Human();

cout << lucife.GetHealth()<<endl;
cout << lucife.GetMagic()<<endl;
cout<<endl;


lucife.~Human();

system("pause");

}


And when I run it:

Lucife is born!
This returns Human::health;
20
This returns this->magic
10
Lucife is killed!
This returns Human::health
20
This returns this->magic
10
is killed!


I have 3 questions:


  1. After I killed instance "lucife" the first time, why did the 2 methods GetHealth() and GetMagic() still worked?

  2. The second time I called ~Human() on instance "lucife", why didn't it print out "Lucife is killed!" like the first time? What exactly happened here? Is the name value deleted?

  3. Does return Human::health and return this->health mean the same thing? I tried it and see that there is no difference. I think both of them return the health of the instance on which the method was called ("lucife" in this case).



Many thanks to you

Answer

As @R and @Rupesh mentioned, you are seeing the behavior that's undefined.

However, if I may provide you with a little more explanation about what's going on in your very specific code in that specific environment, this might be it.

  1. After I killed instance "lucife" the first time, why did the 2 methods GetHealth() and GetMagic() still worked?

First of all, do not call your object's destructor explicitly like that. It will automatically be fired as soon as you get out of the scope main. That's never a good practice.

The reason you can still invoke GetHealth() and GetMagic() is that they are just functions with its first hidden argument to this.

You might be surprised if you see

class AAA
{
public:
    void f() { std::cout << "Hello world" << std::endl; }
}

((AAA*) 0)->f();

able to be compiled and running okay. (depending on your environment).

So even if you invoked a destructor explicitly in the middle of scope hoping that it will literally destruct everything inside, you might still be able to reach this without dereferencing nullptr and successfully give this to the intended functions with any luck.

  1. The second time I called ~Human() on instance "lucife", why didn't it print out "Lucife is killed!" like the first time? What exactly happened here? Is the name value deleted?

It's because when Human::~Human() is fired, the destructor of std::string gets also fired, which ends up tidying.

  1. Does return Human::health and return this->health mean the same thing? I tried it and see that there is no difference. I think both of them return the health of the instance on which the method was called ("lucife" in this case).

No, they are different. However in your code, Human::health is just converted to this->health because you used that inside the class Human.

Comments