C++ 静态变量
宇龍_ 人气:0前言
C/C++中的静态变量,相信大多数人都用过,但你很可能用错了,包括你现在所在的项目中都可能埋着这个坑,不信我们往下看!
正文
我们先来看一段大家常写的代码,很简单,这段代码没啥坑:
#include <stdio.h> int GetData() { static int a = 0; return a++; } int main() { for (int i = 0; i < 100; ++i) { printf("%d\n", GetData()); } }
大家都清楚,静态变量只初始化一次,所以GetData调用了100次,打印的结果也是0-99,想必大家都很清楚 ,那请问GetData中初始化变量a的代码只会执行一次?是在哪个阶段初始静态局部变量a的?
想必大家都能回答上来,静态局部变量a的生命周期从程序运行开始就已经存在并初始化了的,并非是在GetData函数中初始化的,但又不完全对,我们看下一段代码:
#include <stdio.h> int GetA() { return 0; } int GetData() { static int a = GetA(); return a++; } int main() { for (int i = 0; i < 100; ++i) { printf("%d\n", GetData()); } }
看了这段代码,不知道大家有没有懵逼?问题来了,请问GetA函数会被调用几次?静态局部变量a是在什么时候初始化的?给大家5秒钟思考!
OK!静态局部变量无论如何都只会初始化一次,这是没有毛病的,但此时静态局部变量a是在第一次调用GetData函数的时候才被初始化的,与前一个例子用常量初始化静态变量并不相同,当然生命周期还是从程序运行开始到程序结束为止。
那编译器是怎么初始化静态变量a的呢?编译器会改造GetData方法如下:
int GetData() { static bool init = false; if (!init) { a = GetA();//a已经被定义在全局了 init = true; } return a++; }
这样编译器就可以保证静态变量a在GetData函数内只被初始化一次,但请问a的初始化是否线程安全?
当然,不同编译器的实现并不相同,有的编译器会在初始化全局变量a的时候用上临界区等,以保证初始化的线程安全,有的却并没有,当然为了自己的代码兼容性更强,建议不要这样写,随便换个方法都能替代。或者只使用常量去初始化静态变量,这能保证线程安全!
总结,编译器在我们不知道的地方默默付出,大家要知道感恩!
加载全部内容