method on deleted instance of class still work?

2020-04-12 10:10发布

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

4条回答
唯我独甜
2楼-- · 2020-04-12 10:12

I'm still learning about stackoverflow and those who post here. Strange environment....

Okay... First, use a pointer to your pointer to your object, then your "const" declarations and the variables defined... I'm not quite sure what your goal is here but they're mismatched (in the way you're using them). Next, you don't need to use the "this" pointer in your method.

Remember that memory management (in C++) is YOUR responsibility. If you need / want to call the destructor, then do it through the "delete" process.

Human *pLucifer = new Human (20,10,"Lucifer");

cout << pLucifer->GetHealth()<GetMagic()<

delete pLucifer;

Disregard the other answer posts you've received as the "Human" object was created on the stack and even though you've called the destructor explicitly, the memory management will not be processed until the function terminates (in this case... main). So the reason your data is still accessible after you've explicitly called the destructor (naughty! Don't do that) is because the stack is still in tact and however you reference it (the stack), you'll be able to get what data resides there. Hope it helps

查看更多
混吃等死
3楼-- · 2020-04-12 10:13

You are seeing the symptoms of undefined behavior.

From the C++ Standard:

12.4 Destructor

...

15 Once a destructor is invoked for an object, the object no longer exists; the behavior is undefined if the destructor is invoked for an object whose lifetime has ended (3.8). [ Example: if the destructor for an automatic object is explicitly invoked, and the block is subsequently left in a manner that would ordinarily invoke implicit destruction of the object, the behavior is undefined. — end example ]

查看更多
叛逆
4楼-- · 2020-04-12 10:15

Might be the reason why the contents are still there (correct me if I'm wrong).

From C++, Free-Store vs Heap,

The free store is one of the two dynamic memory areas, allocated/freed by new/delete. Object lifetime can be less than the time the storage is allocated; that is, free store objects can have memory allocated without being immediately initialized, and can be destroyed without the memory being immediately deallocated. During the period when the storage is allocated but outside the object's lifetime, the storage may be accessed and manipulated through a void* but none of the proto-object's nonstatic members or member functions may be accessed, have their addresses taken, or be otherwise manipulated.

And I agree with @R Sahu that what you are trying to do is undefined.

查看更多
smile是对你的礼貌
5楼-- · 2020-04-12 10:25

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.

查看更多
登录 后发表回答