全局对象何时析构

wyylbl 2007-09-20 03:22:02
我用下面的程序简单测试了一下全局对象,它在main函数执行前被构造,但什么时候析构呢?
#include <iostream>
#include <string>
using namespace std;

class Student
{public:
Student(int n,string nam,char s)
{num=n;
name=nam;
sex=s;
cout<<"Constructor called."<<num<<endl;
}
~Student()
{cout<<"Destructor called."<<num<<endl;}

private:
int num;
string name;
char sex;
};


Student stud1(10010,"Wang_li",'f');

int main()
{
Student stud2(10011,"Zhang_fun",'m');
return 0;
}

运行结果:
Constructor called.10010
Constructor called.10011
Donstructor called.10011

结果中没有显示出全局对象的析构信息,我跟踪调试时也没有查到,请问各位全局对象什么时候被析构


...全文
738 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
skyell 2007-09-21
  • 打赏
  • 举报
回复
高深,深入学习
wyylbl 2007-09-21
  • 打赏
  • 举报
回复
谢谢大家!
我的编译环境是VC6.0
cmoring 2007-09-21
  • 打赏
  • 举报
回复
在main退出后析构!
在windows的,exit/ExitProcess是无法析构全局对象的。
fish6344 2007-09-20
  • 打赏
  • 举报
回复
deng2000() ( ) 信誉:100 )说的也是问题的解的一部份,这也是我想补充我,呵,英雄所见略同!
deng2000 2007-09-20
  • 打赏
  • 举报
回复
楼主所遇到现象应该是全局变量析够顺序造成的.

注意cout本身也是一个全局变量.C++标准没有规定全局变量的析够顺序(换句话说,顺序依赖于编译器).因此,在main()返回后,如果cout先被析够,虽然stud1随后也析构了,但其析构函数中cout<<"Destructor called."...一句会有问题,因为cout已被销毁了,可能什么也不显示(有可能更糟的结果是出异常,这依赖于cout的具体实现.一句话,结果不可预料).

如果用printf()而不是cout来显示析构信息就不会有问题了.

这个小问题给我们一个提示: 不要在全局变量的析构函数中访问另一个全局变量.你没法知道它还在不在.
星羽 2007-09-20
  • 打赏
  • 举报
回复
alt + f5 运行

结果

Constructor called.10010
Constructor called.10011
Destructor called.10011
Destructor called.10010
请按任意键继续. . .


nulldotnet 2007-09-20
  • 打赏
  • 举报
回复
如果是vs 编译器, lz 可以去window 核心编程 - 进程章, 全局对象在mainz之前构造, 在main退出之后销毁(前提是main 正常退出)。 如果某个线程 调用了 ::ExitProcess() 结束进程, 那么全局对象不能够被析够, 但是进程结束后系统资源都会被回收。
独孤过儿 2007-09-20
  • 打赏
  • 举报
回复
全局对象在main()之前被构造,在main()结束之后被析构。

但我只是说全局对象哦,不包括一些局部对象。例如下面的程序,全局对象没有问题,局部对象

的析构函数则不会被调用,就是因为“霸道”的exit()函数,看下面的代码:

#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;

class tmp{
public:
tmp( string s )
{
cout<<"Constructor!"<<s<<endl;
str = s;
}
~tmp()
{
cout<<"Destructor!"<<str<<endl;
}
private:
string str;
};

tmp t1( "t1" );

int main()
{
tmp t2( "s2" );
//exit( 1 );

return 0;
}
运行结果如下:
Constructor!t1
Constructor!s2
Destructor!s2
Destructor!t1


Terminated with return code 0
Press any key to continue ...

如果把exit(1)的注释去掉,结果是这样的:
Constructor!t1
Constructor!s2
Destructor!t1


Terminated with return code 1
Press any key to continue ...

ivy1023 2007-09-20
  • 打赏
  • 举报
回复
实际在main()执行前,有段startup是要执行的,包括寄存器的初始化,全局变量的定义等等.
在main执行完后,也有段代码要执行,而这段代码就用来destruct全局对象.

可以只样试,看程序是怎么运行的;

在自己写的某个类的构造函数中打一个断点,析构函数中也打一个断点,这样就可以跟踪其执行过程.
wwqna 2007-09-20
  • 打赏
  • 举报
回复
GCC可以输出
fish6344 2007-09-20
  • 打赏
  • 举报
回复
首先,引用stanley B.LLppman博士的一句话:

"C++保证,一定会在main()函数中第一次使用全局对象之前,把它构造出来,而在main()函数结束之前,把它摧毁掉!"

所以,全局对象的建构与析构是语言对我们的庄严承诺。

你的上述程序在VC、BC及Gcc是有不同的屏幕打印输出,其中在我的一个非商业化Gcc编译器上才有一如我们预期的输出:

Constructor called.10010
Constructor called.10011
Destructor called.10011
Destructor called.10010

现代C++编译器(主要是指特定平台的),通过扩充链接器和目标文件格式,完成全局对象的建构初始化和析构,(VC的链接器不是就把winmain()函数帮我们加入到.exe中,弄得许多学MFC的人看不到程序的主体而疑惑!),所以上述不同的编译器对该程序有不同的表现,是因为它们的链接器及目标文件格式,进一步说是对全局对象的静态初始化与析构实现稍有不同的原故!但它们都一定实现了关于全局对象的建构与析构的语言特性。
nkgd 2007-09-20
  • 打赏
  • 举报
回复
你什么编译器,什么运行环境?
wyylbl 2007-09-20
  • 打赏
  • 举报
回复
to nkgd(长歌天下)
我运行的结果只有
Constructor called.10010
Constructor called.10011
Donstructor called.10011
没有 Destructor called.10010 这条语句啊!

ckt 2007-09-20
  • 打赏
  • 举报
回复
在main()函数退出时,或者exit()被调用时
全局对象的析构被调用


你可以使用在析构中使用语句 OutputDebugString("Destructor called.");
//要include Windows.h
用debugview查看
nkgd 2007-09-20
  • 打赏
  • 举报
回复
怎么会没有析构,运行输出如下:
Constructor called.10010
Constructor called.10011
Destructor called.10011
Destructor called.10010
xugang_2001 2007-09-20
  • 打赏
  • 举报
回复
全局对象可以理解为在编译阶段就已经构造好了,所以会在mian之前就已经构造,至于析够,肯定也是在main结束以后才会发生,所以我们无法跟踪,但是可想而知了。

64,701

社区成员

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

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