• C/C++中的静态变量注意事项(很多人都会踩坑,甚至现在还不明白)


    前言

    C/C++中的静态变量,相信大多数人都用过,但你很可能用错了,包括你现在所在的项目中都可能埋着这个坑,不信我们往下看!

    正文

    我们先来看一段大家常写的代码,很简单这段代码没啥坑

    1. #include
    2. int GetData()
    3. {
    4. static int a = 0;
    5. return a++;
    6. }
    7. int main()
    8. {
    9. for (int i = 0; i < 100; ++i)
    10. {
    11. printf("%d\n", GetData());
    12. }
    13. }

    大家都清楚,静态变量只初始化一次,所以GetData调用了100次,打印的结果也是0-99,想必大家都很清楚 ,那请问GetData中初始化变量a的代码只会执行一次?是在哪个阶段初始静态局部变量a的?

    想必大家都能回答上来,静态局部变量a的生命周期从程序运行开始就已经存在并初始化了的,并非是在GetData函数中初始化的,但又不完全对,我们看下一段代码:

    1. #include
    2. int GetA()
    3. {
    4. return 0;
    5. }
    6. int GetData()
    7. {
    8. static int a = GetA();
    9. return a++;
    10. }
    11. int main()
    12. {
    13. for (int i = 0; i < 100; ++i)
    14. {
    15. printf("%d\n", GetData());
    16. }
    17. }

    看了这段代码,不知道大家有没有懵逼?问题来了,请问GetA函数会被调用几次静态局部变量a是在什么时候初始化的?给大家5秒钟思考!

    OK!静态局部变量无论如何都只会初始化一次,这是没有毛病的,但此时静态局部变量a是在第一次调用GetData函数的时候才被初始化的,与前一个例子用常量初始化静态变量并不相同,当然生命周期还是从程序运行开始到程序结束为止。

    那编译器是怎么初始化静态变量a的呢?编译器会改造GetData方法如下:

    1. int GetData()
    2. {
    3. static bool init = false;
    4. if (!init)
    5. {
    6. a = GetA();//a已经被定义在全局了
    7. init = true;
    8. }
    9. return a++;
    10. }

    这样编译器就可以保证静态变量a在GetData函数内只被初始化一次,但请问a的初始化是否线程安全?

    当然,不同编译器的实现并不相同,有的编译器会在初始化全局变量a的时候用上临界区等,以保证初始化的线程安全,有的却并没有,当然为了自己的代码兼容性更强,建议不要这样写,随便换个方法都能替代。或者只使用常量去初始化静态变量,这能保证线程安全

    总结,编译器在我们不知道的地方默默付出,大家要知道感恩!

  • 相关阅读:
    车用尿素交易暴增丨化工出口ERP让业务管理更高效
    交换两数整有几种途径
    基于Ingress实现灰度发布(金丝雀发布)和蓝绿发布
    代理模式简单举例
    MySQL-sql的优化
    NetMvc通过亚马逊方式服务器端和客户端上传MinIO顺利解决
    Android Studio新建项目下载依赖慢,只需一个操作解决
    442. 数组中重复的数据
    【题解】JZOJ3854 分组
    【04】Spring源码-手写篇-手写AOP实现(下)
  • 原文地址:https://blog.csdn.net/Think88666/article/details/126004224