class 的已删除实例上的方法仍然有效吗?

method on deleted instance of class still work?

我在 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");

}

当我 运行 它时:

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!

我有 3 个问题:

  1. 我第一次杀死实例"lucife"后,为什么GetHealth()和GetMagic()这两个方法仍然有效?
  2. 我第二次在实例 "lucife" 上调用 ~Human() 时,为什么它没有像第一次那样打印出 "Lucife is killed!"?这里到底发生了什么? name值是否被删除?
  3. return Human::health 和 return this->health 是同一个意思吗?我试了一下,发现没有区别。我认为它们都 return 调用该方法的实例的运行状况(在本例中为 "lucife")。

非常感谢你

您看到了未定义行为的症状。

来自 C++ 标准:

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 ]

可能是内容仍然存在的原因(如果我错了请纠正我)。

来自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.

我同意@R Sahu 的观点,即您正在尝试做的事情是未定义的。

我仍在学习 Whosebug 和 post 的那些人。陌生的环境....

好的...首先,使用指向对象指针的指针,然后是 "const" 声明和定义的变量...我不太确定您的目标是什么,但它们'重新不​​匹配(以您使用它们的方式)。接下来,您不需要在方法中使用 "this" 指针。

请记住,内存管理(在 C++ 中)是您的责任。如果你需要/想要调用析构函数,那么通过"delete"过程来完成。

人类 *pLucifer = 新人类 (20,10,"Lucifer");

cout << pLucifer->GetHealth()删除pLucifer;

忽略您收到的其他答案 post,因为 "Human" 对象是在堆栈上创建的,即使您明确调用了析构函数,也不会处理内存管理直到函数终止(在这种情况下......主要)。因此,在明确调用析构函数(调皮!不要那样做)之后,您的数据仍然可以访问的原因是因为堆栈仍然完好无损,无论您如何引用它(堆栈),您都可以得到那里有什么数据。希望对你有帮助

正如@R 和@Rupesh 所提到的,您看到的行为是未定义的。

但是,如果我可以为您提供更多关于您在特定环境中的特定代码中发生的事情的解释,可能就是这样。

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

首先,不要那样明确地调用对象的 destructor。 一旦您离开范围 main,它就会自动触发。这绝不是一个好习惯。

您仍然可以调用 GetHealth()GetMagic() 的原因是它们只是函数,其第一个隐藏参数为 this

如果你看到

,你可能会感到惊讶
class AAA
{
public:
    void f() { std::cout << "Hello world" << std::endl; }
}

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

可以编译并且 运行 可以。 (取决于您的环境)。

因此,即使您在范围中间显式调用了一个析构函数,希望它会真正破坏内部的所有内容,您仍然可以在不取消引用 nullptr 的情况下达到 this 并成功地给出 this 祝你好运。

  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?

这是因为当 Human::~Human() 被触发时,std::string 的析构函数也被触发,最终 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).

不,它们是不同的。 但是在您的代码中,Human::health 只是转换为 this->health 因为您在 class Human.

中使用了它