繁体   English   中英

什么使静态变量只初始化一次?

[英]What makes a static variable initialize only once?

我注意到如果在代码中初始化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

是的,编译器通常会生成一个隐藏的布尔值“这已被初始化了吗?” 标志和每次执行该函数时运行的if

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

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

ZoogieZork对AndreyT答案的评论涉及一个重要方面:静态局部变量的初始化 - 在某些编译器上包括GCC - 默认是线程安全的 (编译器命令行选项可以禁用它)。 因此,它使用一些线程间同步机制(某种互斥或某种原子操作),这种机制可能相对较慢 如果你不熟悉 - 性能明智 - 在你的函数中明确使用这样的操作,那么你应该考虑是否有一个影响较小的替代变量的懒惰初始化(即你自己以线程安全的方式明确地构造它)某处只有一次)。 很少有功能对性能非常敏感,但这很重要 - 不要让它破坏你的一天,或者让你的代码更复杂,除非你的程序太慢而你的探测器指的是那个区域。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM