四种不同对象的生存方式(栈、堆、全局、局部静态)

四种不同对象的生存方式(栈、堆、全局、局部静态)

//东软2012-11月笔试题

class Sample
{
       int x;
public:
      Sample(int a)
       {
              x = a;
              cout << "constructing object: x =" << x << endl;
       }
};

void func(int n)
{
       static Sample obj(n);
}

int main()
{
       func(1);
       func(10);  //1
       return 0;

}

           

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

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

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

  class CDemo
{
public:
       CDemo(const char* str);
       ~CDemo();
       void showObjectName();   //显示对象名。

private:
       char name[20];
};

 
CDemo::CDemo(const char* str)
{
      strncpy_s(name,str,20);
       cout << "Constructor called for " << name << "\n";
}

CDemo::~CDemo()
{
       cout << "Destructor called for " << name << "\n";
};

void func()
{
       CDemo LocalObjectInFunc("LocalObjectInFunc"); //5  //10
       static CDemo staticObject("StaticObject"); //6   
       CDemo* pHeapObjectInFunc = new CDemo("HeapObjectInFunc"); //7 //11
       cout << "Inside func" << endl; //8 //12
} //9析构LocalObjectInFunc //13析构LocalObjectInFunc

void CDemo::showObjectName()   //显示对象名
{
       cout << name << "\n";
}

CDemo GlobalObject("GlobalObject"); //1
 
int main()
{
       CDemo localObjectInMain("LocalObjectInMain");  //2
       CDemo* pHeapObjectInMain = new CDemo("HeapObjectInMain"); //3
 
       cout << "In main, before calling func\n\n\n"; //4
       func();
       cout << "\n\n";                             //13'

       func();                 //staticObject静态对象已经存在,不再创建!                                    
       cout << "\n\nIn main, after calling func\n";  //14

       //test作用域
       //staticObject.showObjectName();  //error C2065: “staticObject”: 未声明的标识符
       //cout << "In main, after GlobalObject.showObjectName(): ";
       //GlobalObject.showObjectName();

       return 0;
}//15析构localObjectInMain //16析构staticObject //17析构GlobalObject


 

执行结果如下:

     

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

 

生存方式

执行时机

消亡时机

全局(静态)对象

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

 

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页