为什么我把一个类的析构函数调用了两次,都能正确执行?

oCplus 2004-09-09 08:34:31
代码如下:

#include <iostream.h>
class a
{
public:
a(int _x)
{
x=_x;
}
int getA()
{
return x;
}
~a()
{
cout<<"i am distructor!";
}
private:
int x;
}
main()
{
int x;
a * _a=new a(100);
x=_a->getA();
cout<<"x is :"<<x<<endl;
_a->~a();
_a->~a();
cin>>x;
return 0;
}
想不明白为什么这样,不是析构一次以后就已经没有此对象了吗
...全文
596 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
coyprightbao 2004-09-12
  • 打赏
  • 举报
回复
mark
grayloach1 2004-09-12
  • 打赏
  • 举报
回复
感谢 steedhorse(晨星) ( ) 的解答,也感谢其它各位
呵呵,楼主没给分,我也是也借地提问,感到有点不好意思;-)
kaoken 2004-09-10
  • 打赏
  • 举报
回复
vc++在debug模式下, 对象的生存期结束的时候, 系统会自动调用析构函数吗? 为什么?
oCplus 2004-09-10
  • 打赏
  • 举报
回复
谢谢楼上的大哥哥大姐姐小弟弟小妹妹热心解答,这些我明白了
但是第二个问题还没人解答呢
就是为什么delete一个对象后,怎么还能调用它的析构函数呢?
grayloach1 2004-09-10
  • 打赏
  • 举报
回复
借贵宝地问一下:
是不是构造函数new了对象,析构函数就应该显式delete对象,

to: steedhorse(晨星) ( )
“如果类只是个非常简单的类,那么实际上根本不需要显式的析构函数。”
是不是指在栈里的对象不用显式析构,而堆里的对象,或者其他硬件资源则需要显式析构?


kuailingtong 2004-09-10
  • 打赏
  • 举报
回复
析构函数也是一个函数,如果没有添加delete操作,是不执行任何操作的,
只是在类结束的时候调用一下!
CAOZH 2004-09-10
  • 打赏
  • 举报
回复
new相当于malloc+构造函数;
delete相当于析够函数+free;

不能两次free;
晨星 2004-09-10
  • 打赏
  • 举报
回复
析构函数只是做销毁前的动作,销毁动作当然还是由delete(堆对象)或者栈指针的移动(栈对象)来完成。

由编译器完成的销毁动作由于仅仅回收对象直接占用的内存,所以如果对象内还通过指针间接占用了其他内存,或者占用了其他的系统资源(如文件句柄),就需要在对象销毁前通过析构函数来释放。如果类只是个非常简单的类,那么实际上根本不需要显式的析构函数。

最后,从语法上,析构函数也只是个函数而已,仅从语法上考虑的话,我们可以在析构函数中做任何事,当然包括跟对象销毁没有任何关系的事,比如楼主的程序,析构函数中仅仅打印一行字符串,其他的什么都不做,这都是可以的。调用多次当然也没任何问题。它只是个函数而已,当然可以调用多次,只要你能保证它里边没有不可以多次调用的语句(比如删除同一块内存)就可以了。析构函数真正不同于一般函数的地方在于:在对象销毁之前,它会被自动调用,而一般函数不会被自动调用。
wound979 2004-09-10
  • 打赏
  • 举报
回复
对于析构函数一般是由系统来调用的,
但是有时为了能够比较彻底的释放资源,要在析构函数中增加一些delete的语句。一般来说,你手工来调用,并不能保证能正确执行析构函数
njSeeWhy 2004-09-10
  • 打赏
  • 举报
回复
析构函数不是用来销毁对象的,只是在对象生存期结束以前给你一个机会释放所占用的资源。本质上析构函数也是一个函数,只要它所属的对象存在,你调用它几次都没问题。当然,如果你在析构函数里释放了某些资源,那因再次调用导致重复释放而造成的问题就不再此列了,呵呵。
oCplus 2004-09-10
  • 打赏
  • 举报
回复
没人知道吗
beyondtkl 2004-09-10
  • 打赏
  • 举报
回复
向 晨星老大 学习!^_^
thunderclap 2004-09-10
  • 打赏
  • 举报
回复
最后那句不对。
if (0 <> _a) _a = 0;
thunderclap 2004-09-10
  • 打赏
  • 举报
回复

a * _a=new a(100);//表示在内存分配区里分配一块来保存对象的内存块,
delete _a //释放(并不是删除掉了)这块分配的内存块,使别的进程可以使用这块内存块。
比如说总共的内存分配区有100K,如果你new了100k出来,继续再new就会出错了。
在内存分配区new出来的块,在没经过delete释放以前是不能被再次new的。
delete的意思不是真的删除掉,而只是释放new所分配的内存。内存里的内容是不变的。
直到这个块内存被下次的new所分配并存储进新的内容。

所以当你运行delete _a;这句的时候,指针_a依然指向那块内存。所以你当然可以使用,
但是这个使用就是不合法。
在delete前应该先做这样一件事情。
if (0 <> *_a) *_a = 0; //这样那块分配出的内存的内容被清0了。

chenqing1128 2004-09-10
  • 打赏
  • 举报
回复
你的析构函数没有完成析构。
你的就像个一般的函数。
析构函数是由系统调用的,免去自己手工调用的时候不能正确判断时间的烦恼。
析构函数主要是用来释放资源的,你的函数根本没有用这个功能,把它当一般的函数用了,当然不会出错。
晨星 2004-09-10
  • 打赏
  • 举报
回复
~a()
{
cout<<"x vlaue is:"<<x<<endl;
x = 3;
}
晨星 2004-09-10
  • 打赏
  • 举报
回复
偶没说系统一定就崩溃啊。:P。
只是你访问了已经释放掉了的内存,天知道下次到底会怎样?
你可以再试着修改一些x的值试试看。
oCplus 2004-09-10
  • 打赏
  • 举报
回复
谢谢steedhorse(晨星)大哥!
但是我按照你说的试了一下,系统并没有崩溃!
我把代码改进如下:
//===================code===================
#include <iostream.h>
class a
{
public:
a(int _x)
{
x=_x;
}
int getA()
{
return x;
}
~a()
{
cout<<"x vlaue is:"<<x<<endl;
}
private:
int x;
}
main()
{
int x;
a * _a=new a(100);
x=_a->getA();
cout<<"x is :"<<x<<endl;
_a->~a();
delete _a;
_a->~a();
cin>>x;
return 0;
}
//=====================result========================
x is :100
x value is:100
x value is:100
x value is:-572662307

这时候好像x并不是非法访问
晨星 2004-09-10
  • 打赏
  • 举报
回复
当然,即使有一天你完全理解了这些东西,完全明白了什么情况下不会出问题,那也并不表明“在一个野指针上调用成员函数”是值得提倡地。
晨星 2004-09-10
  • 打赏
  • 举报
回复
To:grayloach1(灰泥鳅)
“是不是指在栈里的对象不用显式析构,而堆里的对象,或者其他硬件资源则需要显式析构?”
可以这么说,对于对象本身占用的内存空间而言,当栈对象作用域结束或者堆对象被delete时,会被自动释放。通常我们需要在析构函数中做的主要是释放那些间接地由该对象的某些指针成员变量所指向的堆对象,以及其他的需要释放的系统资源。

To:oCplus(C++)
“就是为什么delete一个对象后,怎么还能调用它的析构函数呢?”。
你的问题很好,要回答好这个问题涉及了很多东西。现在我觉得你可以不必全部都一下子弄明白,只要记住p只是个指针,在指针上执行该指针类型所允许的操作在编译时是永远通过的。对于编译器而言,p->f()能否被编译通过,仅仅依赖于f是不是p的类型的一个成员函数,而不依赖于p运行时会有什么样的值。
而真正到了运行时,当p所指向的对象已经被释放之后,这种调用会不会出问题呢?只要f没有操纵类的非静态成员,就不会。否则一定会,即使你的程序没有崩溃,那也只是运气,只是表面现象。实际上则肯定发生了一些非法的访问。
你的析构函数仅仅打印了一行字符串,当然没有操纵类的任何成员,所以没有问题。
如果你不能完全理解这些,可以暂时先放一放,随着以后你对C++理解的逐渐加深,以后都会明白的,C++本来就不是一门可以轻易一下子都搞明白的语言。:)




加载更多回复(3)

64,642

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧