四种不同对象的生存方式

东软2012-11月笔试题

  1. <SPAN style="FONT-SIZE: 14px">class Sample  
  2. {  
  3.        int x;  
  4. public:  
  5.       Sample(int a)  
  6.        {  
  7.               x = a;  
  8.               cout << "constructing object: x =" << x << endl;  
  9.        }  
  10. };  
  11.   
  12. void func(int n)  
  13. {  
  14.        static Sample obj(n);  
  15. }  
  16.   
  17. int main()  
  18. {  
  19.        func(1);  
  20.        func(10);  //1   
  21.        return 0;  
  22.   
  23. }  
  24.   
  25. </SPAN>  

           

       [分析]题目的考查点,静态对象的创建及执行。类中的静态对象只会执行一次,这是输出上面结果的原因。

       [扩展分析]此种静态对象的题目之前在360面试的时候被问到过,后来在《深入浅出MFC》基础部分讲解C++重要性质之——C++程序的生与死:兼谈构造函数与析构函数部分的示例很能说明问题。

       笔者对示例稍稍做了扩充,如下:

  1. <SPAN style="FONT-SIZE: 14px">  class CDemo  
  2. {  
  3. public:  
  4.        CDemo(const char* str);  
  5.        ~CDemo();  
  6.        void showObjectName();   //显示对象名。   
  7.   
  8. private:  
  9.        char name[20];  
  10. };  
  11.   
  12.    
  13. CDemo::CDemo(const char* str)  
  14. {  
  15.       strncpy_s(name,str,20);  
  16.        cout << "Constructor called for " << name << " ";  
  17. }  
  18.   
  19. CDemo::~CDemo()  
  20. {  
  21.        cout << "Destructor called for " << name << " ";  
  22. };  
  23.   
  24. void func()  
  25. {  
  26.        CDemo LocalObjectInFunc("LocalObjectInFunc"); //5  //10   
  27.        static CDemo staticObject("StaticObject"); //6      
  28.        CDemo* pHeapObjectInFunc = new CDemo("HeapObjectInFunc"); //7 //11   
  29.        cout << "Inside func" << endl; //8 //12   
  30. //9析构LocalObjectInFunc //13析构LocalObjectInFunc   
  31.   
  32. void CDemo::showObjectName()   //显示对象名   
  33. {  
  34.        cout << name << " ";  
  35. }  
  36.   
  37. CDemo GlobalObject("GlobalObject"); //1   
  38.    
  39. int main()  
  40. {  
  41.        CDemo localObjectInMain("LocalObjectInMain");  //2   
  42.        CDemo* pHeapObjectInMain = new CDemo("HeapObjectInMain"); //3   
  43.    
  44.        cout << "In main, before calling func "//4   
  45.        func();  
  46.        cout << " ";                             //13'   
  47.   
  48.        func();                 //staticObject静态对象已经存在,不再创建!                                       
  49.        cout << " In main, after calling func ";  //14   
  50.   
  51.        //test作用域   
  52.        //staticObject.showObjectName();  //error C2065: “staticObject”: 未声明的标识符   
  53.        //cout << "In main, after GlobalObject.showObjectName(): ";   
  54.        //GlobalObject.showObjectName();   
  55.   
  56.        return 0;  
  57. }//15析构localObjectInMain //16析构staticObject //17析构GlobalObject   
  58.   
  59.   
  60. </SPAN><SPAN style="COLOR: black"><SPAN style="FONT-FAMILY: Times New Roman; FONT-SIZE: 14px"> </SPAN></SPAN>  
     

执行结果如下:

     

       [结果分析,引申出四种对象]

 

生存方式

执行时机

消亡时机

全局(静态)对象

全局静态存储区 global

比程序进入点更早,构造函数先被执行;

程序结束前,其析构函数被执行。

局部静态对象

局部静态存储区 local static

在对象诞生时,其构造函数被执行。(注意,此处只会有一个实例产生,而且固定在内存上(非stack也非heap,它的构造函数在控制权第一次移转到其声明处时被调用。

程序将结束时(此对象因而将遭致毁灭)其析构函数才被执行,但比全局对象的析构函数更早一步执行

局部对象

栈区 stack

在对象诞生时,其构造函数被执行。(同局部静态对象

程序流程将离开该对象的存活范围时(以至于该对象将销毁)时,其析构函数被执行。

new方式产生的局部对象

堆区 heap

当对象诞生时,其构造函数被执行。(同局部静态对象、局部对象

在对象被delete时执行析构函数。(注意,不加deleteheap区空间不会自动释放的,如果程序长期运行,会“吃掉”很多内存,造成结果不可预知。)

 

[静态对象的深入探究(全局、局部)]

 

从产生抑制持续到程序结束的那些对象,在这个过程中不会动态的消亡,所以叫静态对象

 

全局静态对象

局部静态对象

1.初始化时机

1)main函数的代码前进行初始化;

2)类中静态、全局对象的初始化时机与该类的对象并无关系(强调:出现在类定义中的静态变量语句只是声明,对于要使用的类的静态成员变量,必须还要在类外进行定义,否则使用时会发生链接错误。声明并不会导致空间的分配,只有定义才会使其被生成。也就是如果你对类的静态成员进行了定义,那么它就肯定会被分配空间并初始化。就像全局变量一样);

初始化发生在函数被调用期间,首次碰到该定义时。

2.举例(区分全局、局部静态对象)

1)定义于namespace的对象;

2)class 函数 file里的static对象;

3)类中的静态变量和全局变量;

定义在函数里的为局部静态对象

3.如何实现的?

对于non-local静态变量的初始化,编译器实际上是这样实现的。对每个编译文件里需要初始化的静态变量,生成一系列的sti_开头的函数,在里面完成初始化调用语句,然后把这些sti_函数抽取出来,形成一个初始化函数表,然后在__main()函数里调用,然后把这个函数放main里的开头

而对于local静态变量,为了实现第一次碰到时初始化,附加了一个全局变量,标志该对象是否被初始化,同时在析构时检查这个变量。这样就保证了第一次碰到时初始化,同时只有在执行了构造函数的时候,才会在程序退出时执行对应的析构函数。

原文地址:https://www.cnblogs.com/davy2013/p/3148933.html