程序如何知道是否需要初始化静态变量?

时间:2018-09-08 18:47:23

标签: c++ initialization thread-safety storage-duration

就像标题中一样-程序如何知道,foo在第二次调用函数时已经被初始化:

int getFoo()
{
    static int foo = 30;
    return foo;
}
int main()
{
    getFoo();
    getFoo();
}

我想知道程序是否存储了有关已初始化哪个静态变量的一些其他信息。

修改:
我在这里找到了答案:
Why does initialization of local static objects use hidden guard flags?
就像我猜到的那样-大多数编译器都存储其他“保护变量”。

2 个答案:

答案 0 :(得分:0)

看看[stmt.dcl]/4

  
      
  1. 具有静态存储持续时间或线程存储持续时间的块范围变量的动态初始化是在控件第一次通过其声明时执行的;此类变量在初始化完成后即被初始化。如果初始化由于抛出异常而退出,则说明初始化未完成,因此下次控件进入声明时会再次尝试初始化。如果在初始化变量时控件同时输入了声明,则并发执行应等待初始化完成。94如果在初始化变量时控件递归地重新输入声明,则行为未定义。
  2.   

答案 1 :(得分:0)

您必须在这里小心。基本static是在编译时初始化的,因此在您的示例中,GetFoo实际上会返回一个常量。

但是...

static(用于初始化对象(或通过调用函数初始化基元))在首次进入声明对象的范围时执行所述初始化。

此外,从C ++ 11开始,这必须以线程安全的方式完成,这会生成很多额外的代码(尽管第一次运行后运行时的开销并不大),这可能是一个问题,例如微控制器,代码大小通常很重要。

这是一个具体的例子:

#include <iostream>

struct X
{
    X () { std::cout << "Initialising m\n"; m = 7; }
    int m;
};

void init_x ()
{
    static X x;
}

int main () {
    std::cout << "main called\n";
    init_x ();
    std::cout << "init_x returned\n";
}

输出:

main called
Initialising m
init_x returned

实时演示:https://wandbox.org/permlink/NZApcYYGwK36vRD4

生成的代码:https://godbolt.org/z/UUcL9s