作者:billy
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

前言

在C语言中,static变量如果初始化,那么初始化发生在任何代码执行之前,属于编译期初始化。全局变量、static全局变量、static局部变量,此三者的生命周期、初始化方法完全一致,只是可见范围不同。

而在C++中我们引入了对象,这给全局变量的管理带领新的麻烦。C++的对象必须由构造函数生成,并最终执行析构操作。由于构造和析构并非分配内存那么简单,可以说相当复杂,因此何时执行全局或静态对象的构造和析构呢?这需要执行相关代码,无法在编译期完成。因此不同的static变量,在不同的时间被初始化,我们需要分情况来讨论。

编译时初始化

如果静态变量本身是基本数据类型(POD),且初始化值是常量,那么这个初始化过程是在编译期间完成的。

static int val = 10;
static char strArray[] = "hello world !";

加载时初始化

程序被加载时立即进行的初始化。这个初始化发生在main函数之前。即使程序任何地方都没访问过该变量, 仍然会进行初始化,因此形象地称之为"饿汉式初始化"。

  1. 静态变量是一个基本数据类型,但是初始值非常量
static int *p = new int[1024];int x = 3;
int y = 4;
static int z = x + y;
  1. 静态变量是一个类对象,这种情况下即使是使用常量初始化,也是加载时初始化,而不是编译时初始化
static std::string str = "Hello world !";class MyClass {
public: MyClass();    MyClass(int a, int b)
;};static MyClass* MyClass1 = new MyClass();
static MyClass MyClass2;

运行时初始化

这个初始化发生在变量第一次被引用。
也就是说,从程序执行模型角度看,程序所在进程空间中,哪个线程先访问了这个变量,就是哪个线程来初始化这个变量。因此,相对于加载初始化来说,这种初始化是把真正的初始化动作推迟到第一次被访问时,因而形象地称为"懒汉式初始化"。

int myfunc()
{       static std::string msg = "hello world !";    //运行时初始化
}

static 初始化的原理

例1:
int main()
{for(int x = 5; x < 10; x++){static int y = x;   //第一次被引用时初始化,并且只初始化一次cout << "x = " << x << ", y = " << y << endl;}return 0;
}输出结果:
x = 5, y = 5
x = 6, y = 5
x = 7, y = 5
x = 8, y = 5
x = 9, y = 5
例2:
int main()
{for(int x = 5; x < 10; x++){static int y = x;cout << "x = " << x << ", y = " << y << endl;int *p = &y;p++;*p = 0;}return 0;
}输出结果:
x = 5, y = 5
x = 6, y = 6
x = 7, y = 7
x = 8, y = 8
x = 9, y = 9

通过两个例子的结果我们可以知道,静态变量的初始化就是通过静态变量后面的一个32位内存位来做记录,以标识这个静态变量是否已经初始化。每次运行到当前位置,会先去判断这个地址:
如果不是1,就给它赋值1,然后给变量赋值;
如果是1,直接跳过赋值代码块这样它就做到了只赋值一次的效果;

在例2中我们每次都将这个值赋值为0,所以程序就一直认为变量一直没有被初始化过,并每次都初始化。该操作并非一个原子操作,因此从代码逻辑角度来说,static变量并不具有“线程安全”性能。

总结

  1. 如果是编译时和加载时初始化,是不会存在线程安全这个问题的。因为这两种初始化一定发生在Main函数执行之前,这个时候尚未进入程序运行空间,而这些初始化一定是在单线程环境下操作的。
  2. 如果是运行时初始化,因为无法保证访问这个静态变量一定只会从某个特定的线程中被访问,因此会存在"线程安全"的问题。

C++中static变量的初始化相关推荐

  1. C++类中成员变量的初始化总结

    C++类中成员变量的初始化总结 1. 普通的变量: 一般不考虑啥效率的情况下 可以在构造函数中进行赋值.考虑一下效率的可以再构造函数的初始化列表中进行.  1 class CA   2 {   3 p ...

  2. c++中static变量的存储duration

    c++中static变量的存储duration static是c++中一个常见的关键字,当修饰全局变量和局部变量时会有不同的效果,同时变量声明初始化与否对生成的二进制文件也有影响. 写了一小段代码测试 ...

  3. 类中static变量和成员变量

    类中static变量和普通变量的区别(一便解释了摘要中的内容) ​ 要理解标题,我们首先来看下static变量本身的特殊之处,即它存储在全局数据区.在类中的static变量也是如此. C++的内存分布 ...

  4. C++类中成员变量的初始化有两种方式

    C++类中成员变量的初始化有两种方式: 构造函数初始化列表和构造函数体内赋值.下面看看两种方式有何不同. 成员变量初始化的顺序是按照在那种定义的顺序. 1.内部数据类型(char,int--指针等) ...

  5. 谨慎Asp.net中static变量的用法

    谨慎Asp.net中static变量的用法 .Net技术 2007-01-30 22:17:37 阅读925 评论11 字号:大中小 谨慎Asp.net中static变量的用法 在.Net平台下进行C ...

  6. Java多线程中static变量的使用

    Java中 没处理好同步 导致两个线程同时为一个static变量赋值 会导致什么后果? Java中 没处理好同步 导致两个线程同时为一个static变量赋值 会导致什么后果?仅仅是多耗资源还是会引发异 ...

  7. Java中final变量的初始化方式

    原文转自:http://blog.csdn.net/zhangjk1993/article/details/24196847 1 public class FinalTest1 { 2 //----- ...

  8. Java中static变量作用和用法详解

    static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念. 被static ...

  9. iOS中 static变量与全局、局部变量的区别 !

    static变量与全局.局部变量的区别 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式. 这两者在存储方式上并 ...

最新文章

  1. 学好Linux必备知识
  2. Oracle 下 unpin 的cursor 才能被移除
  3. c++:MFC中sqlite3的使用(附实际案例)
  4. 能源项目xml文件 -- springMVC-servlet.xml
  5. Java与Python的区别告诉你,学什么看自己
  6. OpenCV-Mat笔记
  7. Docker之DockerFile讲解
  8. java路径两种写法/和\\
  9. windows技巧——notepad2 取代自带 notepad ,功能强大!
  10. 单片机拟真电路图软件_电路仿真软件有哪些?6款常用的电路仿真软件推荐
  11. CodeForces 1023G. Pisces
  12. Mysql中查询系统时间的方法
  13. mysql查询除某一列外的其他列
  14. 信号与系统——零输入与零状态响应之间的比较
  15. 如何用电脑收发传真?电脑怎么收传真?电脑怎么发传真?
  16. 倒计时到0停止,用在手机获取验证码的倒计时
  17. java clone 源码_Java Clone方法之懒人实现
  18. “群舰效应”与商业市场大航海
  19. 圣斗士星矢手游怎么在电脑上玩 圣斗士星矢电脑版教程
  20. 毕业设计 stm32酒驾检测系统 - 单片机 嵌入式 物联网

热门文章

  1. hadoop启动dfs报错: ERROR: Cannot set priority of namenode process 496
  2. 启动时出现提示0xc00000ba错误的程序解决办法
  3. IEEE BigData 2022 | 同济大学第一届面向智能道路巡检的城市数字孪生(征稿与竞赛)...
  4. iPhone问世15年:苹果的成功靠的是用户体验 而不是硬件
  5. java的parseint_Java parseInt()方法
  6. 8页面html作品源代码,Html源代码.doc
  7. Java bho插件,javascript-使用IE插件浏览器帮助器对象(BHO)访...
  8. Python笔记(6)——函数的定义域
  9. select语句详细解释
  10. Kubernetes服务目录的设计