(转-经典-数据段)C++回顾之static用法总结、对象的存储,作用域与生存期

转自:https://blog.csdn.net/ab198604/article/details/19158697
相关知识补充:https://www.cnblogs.com/rednodel/p/9300729.html


 

  在C语言中,static的用法非常简单,只有两种:

        (1)用于函数内部修饰变量,即函数内的静态变量。这种变量的生存期大于函数,使得函数具有一定的“状态”,使用静态变量的函数一般是不可重入的,也不是线程安全的。如strtok(3).

        (2) 用在文件级别,函数体外, 修饰变量或函数,表示该变量或函数只在本文件内可见。其它文件看不到也访问不到该变量或函数。

        在C++中,保留了C的上面用法,除此以外,还有以下两种新用法:

        (1) 用于修饰类的数据成员,即所谓的“静态成员”, 这种数据成员的生存期大于类对象(实例),静态数据成员是每个class有一份, 普通数据成员是每个类对象(实例)有一份。

        (2) 用于修饰类的成员函数,即所谓的“静态成员函数”,这种成员函数也只能访问静态成员和其它静态成员函数,不能访问非静态成员与非静态成员函数。

 

        关于对象的作用域与生存期

        需要明确一点的是,作用域与生存期在某些情况下是不一致的,它们并不等同。下面是存储器模型:

        

        程序在存储器中按上述模型存放,它有代码段,数据段,堆和栈之分。代码段是只读的,数据段分为未初始化的数据段.bss(block started by symbol)和已初始化的数据段.data段。未初始化数据段.bss的特征是在可执行文件中不占空间,在运行时才分配空间,而.data段在编译期间就被初始化,在可执行文件中占据空间。

        对于全局变量

        如int a; 未被初始化,所以它存放在.bss段中

        如int a = 100; 已初始化,故它存放在.data段中.

 

        对于静态全局变量

        如static int a; 未被初始化,它存放在.bss段中

        如static int a = 100; 已初始化,故它存放在.data段中

 

        对于静态局部变量

        如下所示:

 

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     ...  
  4.     {  
  5.         //下面a,b的作用域在{}内,生存期在整个程序的生存期之内  
  6.         static int a; //存储于.bss段中  
  7.         static int b = 100; //存储于data段中。  
  8.     }  
  9. }  


  

 

        对于全局对象与静态全局对象

        如Test g(10); static Test g(10); 它们存放在data段中,但运行时,对象的构造函数都是先于main函数调用的,在main函数结束后自动调用析构函数销毁

 

        对于局部对象

 

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     ....  
  4.     Test t(10);//局部对象在栈上创建,生存期在main块作用域范围之内,main结束后自动调用析构函数销毁  
  5. }  

        如果在以下情况,它将在{}作用域结束后就自动调用析构函数销毁

 

 

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     ...  
  4.     {  
  5.         Test t(10);  //在栈上创建,作用域在{}  
  6.     }//退出{}后就自动销毁对象  
  7. }  

        

 

        对于静态局部对象

        如下:

 

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     ...  
  4.     {  
  5.         //均存储在data段中,作用域在{}之内,生存期在整个main结束后才自动调用析构函数销毁。  
  6.         static Test t(100);   
  7.           
  8.         static Test t2;  
  9.     }  
  10. }  

 

 

         对于堆上的对象

        如下:

 

[cpp] view plain copy
 
  1. int main()  
  2. {  
  3.     ...  
  4.     {  
  5.         Test *t3 = new Test(20); //堆上创建的对象,即使跳出作用域{}也不能自动调用析构函数来释放对象。可见作用域与生存期是不同的。作用域仅仅是对象的可见范围。  
  6.         delete *t3; //主动析构。  
  7.     }  
  8. }  

 

        总而言之,静态全局对象,全局对象,静态局部对象都存储在data段中,静态全局对象与全局对象先于main函数调用构造函数,但它们三个都在main结束后自动调用析构函数销毁对象。堆上对象创建于堆,离开作用域范围后依旧不会自动销毁,需要手动销毁对象。局部对象创建于栈上,离开作用域后自动销毁。只有全局的普通变量才区分.bss段与.data段,未被初始化的全局变量存放在.bss段中,初始化的全局变量存放在data段中,全局变量作用域在整个程序的生命周期。局部变量在栈上创建,作用域在局部。另外切记,作用域与生存期有时并不等同。


 

posted @ 2018-06-25 16:06  小鼬就是我  阅读(553)  评论(0编辑  收藏  举报