首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >静态初始化顺序失败

静态初始化顺序失败
EN

Stack Overflow用户
提问于 2011-03-14 13:19:34
回答 5查看 3.2K关注 0票数 10

在他的“思想在C++”(第10章)中,艾克尔描述了曾傑瑞施瓦茨开创的解决这场惨败的技术。他说,如果我们想要初始化x到100和y到200,并在所有翻译单位之间共享它们,我们创建一个Initializer.h,如下所示:

代码语言:javascript
复制
extern int x;
extern int y;
class Initializer {
   static int initCount;
   // if (initCount++ == 0) x = 100 & y = 200
   /* ... */
};
static Initializer init;

在实现文件中我们有

代码语言:javascript
复制
#include "Initializer.h"
int x;
int y;
int Initializer::initCount;

Eckel说“静态初始化(在实现文件中)将强制所有这些值为零”。

让我考虑以下情况:编译器在包含该头的其他文件之后处理实现文件(这意味着在另一个文件中x和y已经被设置为100和200 )。编译器会看到int x,那么它会做什么呢?它是否会将x和y设置为零,消除初始化和以前文件中所有可能的更改?但是如果是这样的话,那么initCount也将被设置为零,从而破坏了整个技术。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-03-14 13:28:08

如果是

,那么编译器会在另一个文件之后处理实现文件,而不是将x和y设置为零,从而消除初始化和以前文件中所有可能的更改?

我不知道你这么说是什么意思。如果xy是在其他文件中定义的,那么您就会遇到链接器冲突,程序根本就不会编译。

如果xy和最重要的Initializer::initCount是以这种方式实现的,那么程序中就会有它们的唯一实例;它们实际上是全局的,在构建任何Initializer之前,它们将被初始化为0 (由于包含声明该类的static实例的标题)。static Initializer的每个构造都将首先检查是否由于if (initCount++ == 0)等原因而构建了其他Initializer

运行的第一个Initializer ctor (仍在输入main之前)将设置所有三个值。

票数 4
EN

Stack Overflow用户

发布于 2011-03-14 13:48:23

在“初始化程序”中所做的是赋值,而不是初始化(假设有效的语法)。

因此,它“解决”了特殊情况下的静态初始化顺序失败,因为从一开始就没有失败。X和y是整数,它们在不可预测的时间不相互调用,而且它们也生活在同一个翻译单元中。编译器将正确地初始化它们。如果事后按定义的顺序赋值,这很好,但它只是更复杂,而不是更好。

如果要出现静态初始化顺序失败,您需要这样的情况:x的构造函数需要y的值(或者相反的情况),并且它们位于不同的翻译单元中。因此,无论这是否有效,都有50:50的机会。

现在,“初始化器”结构将正确地按定义的顺序赋值,但此时,x和y的构造函数已经运行,因为您不能为未构造的值赋值.因此,如果这个问题存在的话,它根本就不会避免。

第一次使用结构是解决这一问题的常用方法。这种技术有不同的味道(各有其优缺点),例如:

代码语言:javascript
复制
x& get_x() { static x *xxx = new x(); return *xxx; }
票数 3
EN

Stack Overflow用户

发布于 2011-03-14 13:44:15

假设您的意思是在其他源文件中在静态init范围内进行任何可能的使用和初始化,那么您就完全正确了:如果编译器决定在其他文件中运行该文件的静态初始化,那么您将撤销其他工作。

在很多情况下,只要完全不使用全局/静力学,你就可以节省大量的头痛。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5299095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档