我注意到如果你在C++中的代码中初始化静态变量,该初始化仅在第一次运行函数时运行。
这很酷,但它是如何实现的呢?它会被转换为某种扭曲的if语句吗?(如果给定一个值,那么...)
void go( int x )
{
static int j = x ;
cout << ++j << endl ; // see 6, 7, 8
}
int main()
{
go( 5 ) ;
go( 5 ) ;
go( 5 ) ;
}
我注意到如果你在C++中的代码中初始化静态变量,该初始化仅在第一次运行函数时运行。
这很酷,但它是如何实现的呢?它会被转换为某种扭曲的if语句吗?(如果给定一个值,那么...)
void go( int x )
{
static int j = x ;
cout << ++j << endl ; // see 6, 7, 8
}
int main()
{
go( 5 ) ;
go( 5 ) ;
go( 5 ) ;
}
是的,通常会转换成带有内部布尔标志的隐式if
语句。因此,在最基本的实现中,您的声明通常会转换为以下内容:
void go( int x ) {
static int j;
static bool j_initialized;
if (!j_initialized) {
j = x;
j_initialized = true;
}
...
}
此外,如果您的静态对象具有非平凡析构函数,则语言必须遵守另一条规则:这些静态对象的销毁顺序必须与它们的构造顺序相反。由于构造顺序仅在运行时已知,因此销毁顺序也在运行时确定。因此,每次您使用具有非平凡析构函数的本地静态对象进行构造时,程序都必须将其注册在某种线性容器中,以便稍后以适当的顺序销毁这些对象。
不用说,实际细节取决于实现方式。
值得注意的是,当涉及到静态“原始”类型的对象(如您示例中的int
)以编译时常量进行初始化时,编译器可以自由地在启动时初始化该对象。你永远不会注意到任何区别。但是,如果您使用“非原始”对象的更复杂的示例,情况就不同了。
void go( int x ) {
static std::string s = "Hello World!";
...
即使对象使用编译时常量进行初始化,上述带有if
的方法也应该出现在生成的代码中。
在您的情况下,初始化程序在编译时是未知的,这意味着编译器必须延迟初始化并使用隐式的if
。
它们仅被初始化一次,因为这是C++标准规定的。具体实现方式完全取决于编译器供应商。根据我的经验,编译器会生成并使用本地隐藏标志。