转自: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段中

对于静态局部变量

如下所示:

  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函数结束后自动调用析构函数销毁

对于局部对象

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

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

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

对于静态局部对象

如下:

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

对于堆上的对象

如下:

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

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


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

  1. C语言内存分布之数据段

    不管我们以后是自己写代码还是读别人的代码,都应该想想这个变量默认存储的位置.在我们以后的嵌入式开发中,技巧性的代码越来越多的时候,我们可能把某一些代码放在一段.我们可以通过修改变量或者代码默认放置的段 ...

  2. linux代码段,数据段,BSS段, 堆,栈(二)

    //main.cpp int a = 0; 全局初始化区  char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char ...

  3. linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】

    转自:http://blog.csdn.net/gongweijiao/article/details/8207333 原文参见:http://blog.163.com/xychenbaihu@yea ...

  4. C语言全局未初始化数据段分析

    前言: 在分析C语言全局未初始化变量时,发现在目标文件中全局未初始化变量并不是直接放在bss段中. 再后来发现在两个.c文件中定义同名的全局变量,链接时居然没有发生符号重定义错误.才知道C语言弱定义的 ...

  5. 【转】linux代码段,数据段,BSS段, 堆,栈

    转载自 http://blog.csdn.net/wudebao5220150/article/details/12947445  linux代码段,数据段,BSS段, 堆,栈 网上摘抄了一些,自己组 ...

  6. 数据段、代码段、堆栈段、BSS段

    在linux中,进程在内存中一般会分为5个段,用来存放从磁盘载入的程序代码,等. 这五个段分别是: BSS段: 通常用来存放程序中未初始化的全局变量的一块内存区域.属于静态内存分配. 问题:全局变量不 ...

  7. 浅谈c语言代码段 数据段 bss段

    代码段.数据段.bss段 (1)编译器在编译程序的时候,将程序中的所有的元素分成了一些组成部分,各部分构成一个段,所以说段是可执行程序的组成部分. (2)代码段:代码段就是程序中的可执行部分,直观理解 ...

  8. 五个数据段之代码段、数据段、BSS、栈、堆

    继上文讲完了对内存管理的一些知识,下面笔者再对上篇文章的内容加以拓展,那么我们今天就来说一说5个数据段 五个数据段 进程(执行的程序)会占用一定数量的内存,它或是用来存放磁盘载入的程序代码,或是存放取 ...

  9. Unix代码段和数据段

    关于UNIX系统代码段和数据段分开的目的:方便编程. 1)代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像.代码段需要防止在运行时被非法修改,所以只准许读取操作,而 ...

随机推荐

  1. 求链表的倒数第m个元素

    法一: 首先遍历一遍单链表,求出整个单链表的长度n,然后将倒数第m个,转换为正数第n-m+1个,接下去遍历一次就可以得到结果. 不过这种方法需要对链表进行两次遍历,第一次遍历用于求解单链表的长度,第二 ...

  2. 洛谷P2347 砝码称重 【多重背包】(方案数)(经典)

    题目链接:https://www.luogu.org/problemnew/show/P2347 题目描述 设有1g.2g.3g.5g.10g.20g的砝码各若干枚(其总重<=1000), 输入 ...

  3. 第一章 Python入门

    一. 语言 计算机语言:人和计算机之间沟通的语言计算机语言: 按照级别分类:(越高级月进阶人类) 机器语言: 汇编语言: 助记符 ag. add 2 3 高级语言: c, PHP, java , .n ...

  4. 通过反射的方式注入自己的ShutdownHook并清除其他HOOK

    String className = "java.lang.ApplicationShutdownHooks"; Class<?> clazz = Class.forN ...

  5. 洛谷.U19464.山村游行wander(LCT 伪期望)

    题目链接 题意: 森林,动态建边.删边,询问从S开始走到T的期望时间.走位: 每次人会随机地选一条未走过的边走,走到无路可走,再退回.这样直到终点T.走一条边.从一条边退回都花费时间1. 题目特点是走 ...

  6. 潭州课堂25班:Ph201805201 第三课:序列类型的方法 (课堂笔记)

    列表的方法: li = [] 添加: li.append( 'a' ) 追加元素进入列表 li.insert( 1, 'b' ) 插入元素到指定索引位置 ----->>>  li.i ...

  7. [Beijing wc2012]算不出的算式

    OJ题号:BZOJ2659 思路:数学. 建立平面直角坐标系.在第一象限作直线y=qx/p,易得Σ[kq/p]即为当x<(p/2)时,直线下方(包括直线)的整点数:Σ[kp/q]为当y<( ...

  8. 并查集 (Union-Find Sets)及其应用

    定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的 ...

  9. filter的dispatcher节点

    1.FORWARD (1)a.jsp页面内容如此<jsp:forward page="/b.jsp"></jsp:forward> (2) a.jsp页面内 ...

  10. 发布Docker 镜像到dockerhub

    公有仓库 docker提供了一个类似于github的仓库dockerhub, 网址 https://hub.docker.com/ 需要注册使用 注意要保证image的tag是账户名,如果镜像名字不对 ...