• 四种不同对象的生存方式


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

  • 相关阅读:
    WCF学习笔记
    下拉框层级绑定
    js在IE可以运行,在Firefox 不运行
    ajax 基础
    Asp.net Mvc Web Api 学习(一)
    阅读暗时间的笔记与心得
    阅读暗时间的心得与笔记
    阅读暗时间的笔记与心得(结束篇)
    阅读暗时间的笔记与心得
    阅读暗时间的心得与笔记
  • 原文地址:https://www.cnblogs.com/davy2013/p/3148933.html
Copyright © 2020-2023  润新知