C++中如何在main()函数之前执行操作?


多玩YY语音的面试题:C++中如何在main()函数之前执行操作?

           第一反应main()函数是所有函数执行的开始。但是问题是main()函数执行之前如何执行呢?

           联想到MFC里面的 C**App类的theApp对象,其执行顺序就在main函数之前。道理相通,顺理推下,能够想到:如果在main函数之前声明一个类的全局的对象。那么其执行顺序,根据全局对象的生存期和作用域,肯定先于main函数。

示例如下:

[cpp] view plain copy
  1. class simpleClass  
  2. {  
  3. public:  
  4.        simpleClass( )  
  5.        {  
  6.               cout << "simpleClass constructor.." << endl;  //step2  
  7.        }  
  8. };  
  9.   
  10.    
  11. simpleClass g_objectSimple;         //step1全局对象  
  12.   
  13. int _tmain(int argc, _TCHAR* argv[])  //step3  
  14. {  
  15.        return 0;  
  16. }  
  17.   
  18.   
  19. 可单步调试查看执行顺序为step1、step2、step3。

 

考虑到全局对象,同理会进一步思考静态对象的作用域。将上述示例进一步扩展如下:

[cpp] view plain copy
  1. class simpleClass  
  2. {  
  3. public:  
  4.        simpleClass( )  
  5.        {  
  6.               cout << "simpleClass constructor.." << endl;       //step2   
  7.        }  
  8. };  
  9.   
  10. class simpleClassTwo  
  11. {  
  12. public:  
  13.        static simpleClass m_sSimpleClass;  
  14. };  
  15.   
  16. simpleClass simpleClassTwo::m_sSimpleClass = simpleClass(); //step1 静态对象  
  17.   
  18. int _tmain(int argc, _TCHAR* argv[])                        //step3  
  19.   
  20. {  
  21.         return 0;  
  22. }  
  23.   
  24.   
  25. 可单步调试查看执行顺序为step1、step2、step3。

        至此,我们可以总结出:定义在main( )函数之前的全局对象、静态对象的构造函数在main( )函数之前执行

      再进一步思考,既然可以在main( )函数之前执行全局、静态对象的构造函数。那么有没有函数在main( )函数之后执行呢?

有的,onexit函数。原型如下:

_onexit_t _onexit(

   _onexit_t function

);

_onexit_t_m _onexit_m(

   _onexit_t_m function

);

解释:The _onexit function is passed the address of a function (function) to be called when the program terminates normally. Successive calls to _onexit create a register of functions that are executed in LIFO (last-in-first-out) order. The functions passed to _onexit cannot take parameters.

 

核心点:

1)              执行期——程序执行终止的时候;

2)              传递参数——函数的地址,即函数指针;

3)              执行顺序——后进先出。

 

_onexit is a Microsoft extension. For ANSI portability, use atexit. The _onexit_m version of the function is for mixed mode use.

onexit是微软的扩展版本,标准C++里面应用的是atexit。

【MSDN】示例:

[cpp] view plain copy
  1. "font-size:14px;">#include   
  2. #include   
  3. /* Prototypes */  
  4. int fn1(void), fn2(void), fn3(void), fn4 (void);  
  5.   
  6. int main( void )  
  7. {  
  8.       _onexit( fn1 );  
  9.       _onexit( fn2 );  
  10.       _onexit( fn3 );  
  11.       _onexit( fn4 );  
  12.       printf( "This is executed first.\n" );  
  13. }  
  14.   
  15.    
  16. int fn1()  
  17. {  
  18.       printf( "next.\n" );  
  19.       return 0;  
  20. }  
  21.   
  22.    
  23. int fn2()  
  24. {  
  25.       printf( "executed " );  
  26.       return 0;  
  27. }  
  28.   
  29.    
  30. int fn3()  
  31. {  
  32.       printf( "is " );  
  33.       return 0;  
  34. }  
  35.   
  36.    
  37. int fn4()  
  38. {  
  39.       printf( "This " );  
  40.       return 0;  
  41. }  
  42.   

执行结果如下:

       显然,读程序可以看出main( )函数执行完毕后又执行了onexit( )函数。

      还有没有其他特殊的情况呢?持续探讨、更新中……

       2013-4-18


上一篇: 模块化动态划线实现解读

15楼 wojiushiwo987 2小时前发表 [回复]
引用“wangfei584521”的评论:回复v2abcd:你的分析是对的。帖主没有认真看标准c++,只是特定地试了...
谢谢提醒,一些知识点涉猎的不够全面,我会尽快更新上。
14楼 法师org 4小时前发表 [回复]
学习了。。。
13楼 smile588477 昨天 14:39发表 [回复]
学习一下
12楼 0c0c0f 昨天 09:07发表 [回复]
获取指向新进程的完整命令行指针
获取指向新进程环境变量的指针
初始化c/c++运行库的全局变量。
初始化c运行库内存分配函数(malloc和calloc)和其他底层i/o
Re: naw0011 4小时前发表 [回复]
高手哇,我最近在看Windows 核心编程,刚好看到这一块,跟你说的一样,都要初始化进程的一些运行环境相关的东西。
Re: 0c0c0f 4小时前发表 [回复]
回复naw0011:俺就是在核心编程书上找到的,嘿嘿,菜的很!
Re: wojiushiwo987 2小时前发表 [回复]
引用“c0c0cf”的评论:回复naw0011:俺就是在核心编程书上找到的,嘿嘿,菜的很!
我马上补习下核心编程上的知识点,谢谢你!
11楼 0c0c0f 昨天 08:59发表 [回复]
main函数之前先要有启动函数,启动函数完成程序的环境等的初始化!
10楼 pl___ 昨天 02:37发表 [回复]
C++中如何在main()函数之前执行操作?
////
不提倡使用全局变量. 全局变量会有副作用(比如初始化顺序相关的,又比如异常相关的,调试困难,等).
正确的方法是在编译选项里指定一个特殊的函数作为入口点.
更正确的方法是不要依赖全局初始化.
在用的时候多写一行init()或者用构造函数(注意:不要用全局变量)
9楼 dreamgis 昨天 00:11发表 [回复]
mark一下先
8楼 苍穹浪 昨天 23:36发表 [回复]
ISO/IEC C++ N3485
3.6.2 Initialization of non-local variables [basic.start.init]
4 It is implementation-defined whether the dynamic initialization of a non-local variable with static storage
duration is done before the first statement of main. If the initialization is deferred to some point in time
after the first statement of main, it shall occur before the first odr-use (3.2) of any function or variable
defined in the same translation unit as the variable to be initialized.34

注意最后一句,C++标准仅规定非本地变量会在所在的编译单元被调用前初始化,并不保证main前初始化。这种方法在main前执行代码的方式需要依赖编译器实现,不具有可移植性。
Re: Sid的小小屋 13小时前发表 [回复]
回复v2abcd:你的分析是对的。帖主没有认真看标准c++,只是特定地试了微软的c++的实现。
7楼 wojiushiwo987 前天 21:11发表 [回复]
引用“wojiushiwo987”的评论:[quote=williamx]这个和main之前之后是没有关系的,而是全局变量会先于main构造,...
静态对象又分为:局部静态对象和全局静态对象。全局对象和全局静态对象先于main()函数构造,所以执行靠前!
6楼 hubingfeng0803 前天 16:49发表 [回复]
分析的好!
5楼 williamx 前天 15:31发表 [回复]
这个和main之前之后是没有关系的,而是全局变量会先于main构造,所以构造函数会被调用。
4楼 流言翡语 前天 14:05发表 [回复]
在C++里,应该先执行构造函数。
3楼 IGOJAVA 前天 13:42发表 [回复]
在C语言里可以定义函数在main函数前执行(_attribute_),C++应该也差不多吧
2楼 wojiushiwo987 前天 23:14发表 [回复]
引用“Crazy_Number”的评论:析构函数不也是在main()函数执行完毕后释放资源的时候被执行么?
谢谢回复。析构函数主要是指当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。确切的说其和main()函数关系不大。

你可能感兴趣的:(C++)