全局对象何时析构

来源:互联网 发布:ff14人男捏脸数据 编辑:程序博客网 时间:2024/05/01 10:51
 
我用下面的程序简单测试了一下全局对象,它在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

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


20  修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • xugang_2001
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 15:25:391楼 得分:1
全局对象可以理解为在编译阶段就已经构造好了,所以会在mian之前就已经构造,至于析够,肯定也是在main结束以后才会发生,所以我们无法跟踪,但是可想而知了。
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • nkgd
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 15:26:412楼 得分:1
怎么会没有析构,运行输出如下:
Constructor   called.10010
Constructor   called.10011
Destructor   called.10011
Destructor   called.10010
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • ckt1120
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 15:35:113楼 得分:1
在main()函数退出时,或者exit()被调用时  
全局对象的析构被调用


你可以使用在析构中使用语句   OutputDebugString( "Destructor   called. ");  
//要include   Windows.h
用debugview查看
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • wyylbl
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 15:54:564楼 得分:0
to   nkgd(长歌天下)  
我运行的结果只有
Constructor   called.10010
Constructor   called.10011
Donstructor   called.10011
没有   Destructor   called.10010     这条语句啊!

修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • nkgd
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 15:57:245楼 得分:0
你什么编译器,什么运行环境?
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • fish6344
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 16:54:176楼 得分:5
首先,引用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的人看不到程序的主体而疑惑!),所以上述不同的编译器对该程序有不同的表现,是因为它们的链接器及目标文件格式,进一步说是对全局对象的静态初始化与析构实现稍有不同的原故!但它们都一定实现了关于全局对象的建构与析构的语言特性。
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • wwqna
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 17:16:457楼 得分:1
GCC可以输出
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • ivy1023
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 17:23:168楼 得分:2
实际在main()执行前,有段startup是要执行的,包括寄存器的初始化,全局变量的定义等等.
在main执行完后,也有段代码要执行,而这段代码就用来destruct全局对象.

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

在自己写的某个类的构造函数中打一个断点,析构函数中也打一个断点,这样就可以跟踪其执行过程.
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • fetag
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 19:35:579楼 得分:2
全局对象在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   ...

修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • nulldotnet
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 20:47:0610楼 得分:2
如果是vs   编译器,   lz   可以去window   核心编程   -   进程章,   全局对象在mainz之前构造,   在main退出之后销毁(前提是main   正常退出)。   如果某个线程   调用了   ::ExitProcess()   结束进程,   那么全局对象不能够被析够,   但是进程结束后系统资源都会被回收。
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • Chiyer
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
  • 4

    4

    3

发表于:2007-09-20 21:03:0811楼 得分:1
alt   +   f5   运行

结果

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


修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • deng2000
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 21:48:1112楼 得分:2
楼主所遇到现象应该是全局变量析够顺序造成的.

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

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

这个小问题给我们一个提示:   不要在全局变量的析构函数中访问另一个全局变量.你没法知道它还在不在.
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • fish6344
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-20 23:27:1613楼 得分:1
deng2000()   (   )   信誉:100   )说的也是问题的解的一部份,这也是我想补充我,呵,英雄所见略同!
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • cmoring
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-21 13:59:4014楼 得分:1
在main退出后析构!
在windows的,exit/ExitProcess是无法析构全局对象的。
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • wyylbl
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-21 14:19:3615楼 得分:0
谢谢大家!
我的编译环境是VC6.0
修改 删除 举报 引用 回复
进入用户个人空间
加为好友
发送私信
在线聊天
  • skyell
  • 等级:
  • 可用分等级:
  • 总技术分:
  • 总技术分排名:
发表于:2007-09-21 17:35:5816楼 得分:0
高深,深入学习
原创粉丝点击