什么使一个静态variables只初始化一次?

我注意到,如果你用C ++在代码中初始化一个静态variables,初始化只在你第一次运行这个函数的时候运行。

这很酷,但是如何实施? 它是否转化为某种扭曲的陈述? (如果给定一个值,那么..)

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; } ... } 

最重要的是,如果你的静态对象有一个不平凡的析构函数,那么这个语言必须遵守另一个规则:这样的静态对象必须按照其构造的相反顺序被破坏。 由于构build顺序只在运行时才知道,所以销毁顺序也在运行时定义。 所以,每次用非平凡的析构函数构造一个本地静态对象时,程序必须将其注册到某种线性容器中,以后将用它来以适当的顺序来破坏这些对象。

不用说,实际的细节取决于实施。


值得一提的是,当涉及到静态对象的“原始”types(如你的例子中的int ),用编译时常量初始化时,编译器可以在启动时自由地初始化该对象。 你永远不会注意到不同之处。 但是,如果您使用“非原始”对象进行更复杂的示例

 void go( int x ) { static std::string s = "Hello World!"; ... 

那么使用if的上述方法即使在用编译时常量初始化对象时也应该在生成的代码中find。

在你的情况下,初始化器在编译时是不知道的,这意味着编译器必须延迟初始化并使用隐含的if

是的,编译器通常会生成一个隐藏的布尔值“是否已经初始化?” 标志和一个if每次执行该function运行。

这里有更多的阅读材料: 编译器如何实现静态variables初始化?

虽然这确实是“某种扭曲的”,但这种扭曲可能比你想象的要多…

ZoogieZork评论AndreyT的答案涉及到一个重要的方面:静态局部variables的初始化 – 在包括GCC的一些编译器上默认是线程安全的 (编译器命令行选项可以禁用它)。 因此,它使用了一些可能相对较慢的线程间同步机制(某种互斥或者某种primefaces操作)。 如果你不习惯 – 性能明智的话 – 在你的函数中明确使用这样一个操作,那么你应该考虑是否对variables的惰性初始化有一个较低影响的select(例如,自己明确地以线程安全的方式构造它某处只是一次)。 很less有函数对性能敏感,所以这个问题很重要 – 不要让它破坏你的一天,或者让你的代码更加复杂,除非你的程序太慢了,你的分析器会指责这个区域。

它们只被初始化一次,因为这是C ++标准的要求。 这是如何发生的,完全取决于编译器供应商。 根据我的经验,编译器会生成并使用本地隐藏标志。