C++函数中的静态变量的生命周期是多长?

42 浏览
0 Comments

C++函数中的静态变量的生命周期是多长?

如果在函数范围内声明一个变量为 static,它只会被初始化一次并在函数调用之间保留其值。它的生命周期是什么时候?它的构造函数和析构函数何时被调用?

void foo() 
{ 
    static string plonk = "When will I die?";
}

admin 更改状态以发布 2023年5月20日
0
0 Comments

莫蒂在顺序上是正确的,但还有一些其他的事情需要考虑:

编译器通常使用隐藏的标志变量来指示本地静态变量是否已经被初始化,这个标志在每次进入函数时都会被检查。显然,这是一个小的性能损失,但更令人担忧的是,这个标志不能保证是线程安全的。

如果你有一个像上面一样的本地静态变量,并且foo被多个线程调用,可能会出现竞争条件,导致plonk被错误地初始化甚至多次初始化。此外,在这种情况下,plonk可能会在一个不同的线程中被销毁。

尽管标准说的很明确,我还是对本地静态变量的实际销毁顺序非常谨慎,因为有可能你会不知不觉地依赖于静态变量在销毁后仍然有效,而这很难追踪。

0
0 Comments

static变量的生命周期始于程序执行时首次遇到声明的位置,并在程序终止时结束。这意味着运行时必须进行一些簿记,以便只在实际构造时才进行析构。

此外,由于标准规定静态对象的析构函数必须按照它们构造完成的相反顺序运行[1],而构造顺序可能取决于特定的程序运行,所以必须考虑构造顺序。

示例

struct emitter {
    string str;
    emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
    ~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first) 
{
    if (!skip_first)
        static emitter a("in if");
    static emitter b("in foo");
}
int main(int argc, char*[])
{
    foo(argc != 2);
    if (argc == 3)
        foo(false);
}

输出:

C:>sample.exe
在foo中创建
在foo中销毁

C:>sample.exe 1
在if语句中创建
在foo中创建
在foo中销毁
在if语句中销毁

C:>sample.exe 1 2
在foo中创建
在if语句中创建
在if语句中销毁
在foo中销毁

[0]由于C++98没有涉及多线程的引用,因此无法确定其在多线程环境下的行为,可能会出现问题,如Roddy所述。

[1]C++98中,在代码段3.6.3.1 [basic.start.term]有规定。

[2]在C++11中,静态变量以线程安全的方式进行初始化,这也被称为Magic Statics

0