我在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个问题:
非常感谢你
答案 0 :(得分:3)
您正在看到未定义行为的症状。
来自C ++标准:
12.4析构函数
...
15为对象调用析构函数后,该对象不再存在;如果为生命周期结束的对象调用析构函数,则行为未定义(3.8)。 [示例:如果显式调用自动对象的析构函数,并且该块随后以通常调用对象的隐式销毁的方式保留,则行为未定义。 - 结束示例]
答案 1 :(得分:1)
可能是内容仍然存在的原因(如果我错了,请纠正我。)
免费存储是两个动态内存区域之一,由new / delete分配/释放。对象生存期可以小于分配存储的时间;也就是说,免费存储对象可以在不立即初始化的情况下分配内存,并且可以在不立即释放内存的情况下销毁。在分配存储但在对象的生命周期之外的期间,可以通过void *访问和操纵存储,但是可以访问原始对象的非静态成员或成员函数,获取其地址或以其他方式操作
我同意@R Sahu的意见,你要做的事情是不确定的。
答案 2 :(得分:1)
我还在学习stackoverflow和发布在这里的人。奇怪的环境....
好的......首先,使用指向指向对象的指针,然后指向&#34; const&#34;声明和定义的变量...我不太确定你的目标是什么,但它们不匹配(以你使用它们的方式)。接下来,您不需要使用&#34;这个&#34;方法中的指针。
请记住,内存管理(使用C ++)是您的责任。如果你需要/想要调用析构函数,那么通过&#34; delete&#34;过程
Human * pLucifer = new Human(20,10,&#34; Lucifer&#34;);
cout&lt;&lt; pLucifer-&GT; GetHealth()&LT; GetMagic()&LT;
删除pLucifer;
忽略您作为&#34; Human&#34;收到的其他答案帖子。对象是在堆栈上创建的,即使您已明确调用析构函数,在函数终止之前也不会处理内存管理(在本例中为... main)。因此,在您明确调用析构函数(淘气!不要这样做)之后,您的数据仍可访问的原因是因为堆栈仍处于机智状态,无论您引用它(堆栈),您都是&#39 ;能够获得那里的数据。希望它有所帮助
答案 3 :(得分:1)
正如@R和@Rupesh所提到的,您看到的行为未定义。
但是,如果我可以向您提供更多解释,说明在特定环境中您的特定代码中发生了什么,可能就是这样。
- 在我杀死实例后,&#34; lucife&#34;第一次,为什么两个方法GetHealth()和GetMagic()仍然有效?
醇>
首先,不要明确地调用您的对象destructor
。
一旦你离开范围main
,它将自动被触发。这从来都不是一个好习惯。
您仍然可以调用GetHealth()
和GetMagic()
的原因是它们只是具有this
的第一个隐藏参数的函数。
如果你看到
,你可能会感到惊讶class AAA
{
public:
void f() { std::cout << "Hello world" << std::endl; }
}
((AAA*) 0)->f();
能够编译并运行正常。 (取决于您的环境)。
因此,即使您在范围中间显式调用了析构函数,希望它会彻底破坏内部的所有内容,您仍然可以在不解除引用this
的情况下到达nullptr
并成功提供{{1运气好的预期功能。
- 我第二次在实例上打电话给~Heart()&#34; lucife&#34;,为什么没有打印出来&#34; Lucife被杀了!&#34;像第一次?到底是什么 发生在这里?名称值是否已删除?
醇>
这是因为当this
被解雇时,Human::~Human()
的析构函数也会被触发,最终整理。
不,他们是不同的。 但是,在您的代码中,
- 返回Human :: health并返回此 - &gt;健康意味着同样的事情吗?我试过了,看到没有区别。我想两个 它们返回调用该方法的实例的运行状况 (&#34; lucife&#34;在这种情况下)。
醇>
std::string
只是转换为Human::health
,因为您在类this->health
中使用了它。