C/C++中的静态变量注意事项

2022-11-13 13:11:38 变量 静态 注意事项

前言

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的时候用上临界区等,以保证初始化的线程安全,有的却并没有,当然为了自己的代码兼容性更强,建议不要这样写,随便换个方法都能替代。或者只使用常量去初始化静态变量,这能保证线程安全!

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

到此这篇关于C/c++中的静态变量注意事项的文章就介绍到这了,更多相关C++ 静态变量内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

相关文章