繁体   English   中英

C ++标准在哪里说,C在哪里说相同:编译单元(.cpp文件)中的变量按声明顺序初始化

[英]Where does the C++ standard say, and does C say the same: variables in a compilation unit (.cpp file) are initialised in order of declaration

是说

C ++保证按声明顺序初始化编译单元(.cpp文件)中的变量

对于C同样吗?

您可以引用C和C ++的相关标准段落吗?

让我们从C开始。向C询问就像是在问:如果一棵树掉在森林里,没人在周围听到它,它会发出声音吗? 没关系,因为没有任何方法可以编写有效的C程序来说明差异。 这意味着标准对此没有意义。 我们需要知道的是,到任何代码运行时,具有静态存储持续时间的变量都已初始化。 C11标准草案在5.1.2节中进行了详细说明:

程序启动前,所有具有静态存储持续时间的对象都应初始化(设置为其初始值)。 否则未指定这种初始化的方式和时间。

另一方面,在C ++中,事情并非那么简单。 在动态初始化期间可以观察初始化的顺序。 标准草案中,我们找到了3.6.2节。 它很快变得复杂。 它将顺序定义为:首先我们进行静态初始化(这等效于C可以做的唯一事情),然后完成动态初始化。 到现在为止还挺好。 我们到这一部分:

在单个转换单元中定义了有序初始化的变量,应按其在转换单元中定义的顺序进行初始化。

而且世界上一切都还好。 但是事情很快就崩溃了:

允许实现以静态存储持续时间执行非局部变量的初始化作为静态初始化,即使这种初始化不需要以静态方式完成

这句话使我们从一个可以预见的世界转向“它很复杂”。 标准的该部分中的代码示例对此进行了完美解释:

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1;   // unspecified:
                  // may be statically initialized to 0.0 or
                  // dynamically initialized to 0.0 if d1 is
                  // dynamically initialized, or 1.0 otherwise
double d1 = fd(); // may be initialized statically or dynamically to 1.0

简而言之,在C语言中没关系,在C ++中,如果编写依赖于此的代码,则在更改编译器时很可能会遇到麻烦。

因此,您的报价是双重错误的。 初始化不仅没有按照声明的顺序进行(先是静态,然后是动态),而且实际上是静态的还是动态的也很模糊。

在C ++中,必须定义初始化的顺序,因为可能存在在变量的初始化中调用的构造函数。 因此,C ++定义了此代码的执行顺序。 在普通C中,没有构造函数。 只要在执行任何可以访问该变量的代码之前就初始化每个变量,就无法确定变量的初始化顺序。

C标准(C11)6.7.6说

完整声明符是不属于另一个声明符的声明符。 完整声明符的末尾是一个序列点。

这意味着在每个声明的末尾,必须完成初始化并且必须对所有子表达式进行副作用评估。

未指定实际代码的执行时间。 这意味着可以在进行初始化的行之前很长时间完成,但不能在该行之后完成。

具有静态存储持续时间的变量是一种特殊情况,因为可以保证在程序启动之前对其进行初始化。 它们的执行顺序在C语言中无关紧要,因为它们彼此不依赖(必须初始化为常量表达式)。

在C ++中,具有静态存储持续时间的类对象以未指定的顺序初始化,因此不应编写它们,以便它们彼此依赖以特定的顺序进行初始化。

另请注意6.7.9 / 23:

初始化列表表达式的求值相对于彼此不确定地排序,因此未指定发生任何副作用的顺序。

这意味着我们不知道执行同一声明的所有初始化程序部分的顺序。

我相信C和C ++在上述所有方面都是相同的,尽管C ++还将在初始化过程中执行构造函数。

暂无
暂无

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

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