简体   繁体   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

Here it is states that 是说

C++ guarantees that variables in a compilation unit (.cpp file) are initialized in order of declaration C ++保证按声明顺序初始化编译单元(.cpp文件)中的变量

Is this the same for C? 对于C同样吗?

Can you quote the relevant standard passages for both C and C++? 您可以引用C和C ++的相关标准段落吗?

Let's start with C. Asking this for C is like asking: If a tree falls in a forest and no one is around to hear it, does it make a sound? 让我们从C开始。向C询问就像是在问:如果一棵树掉在森林里,没人在周围听到它,它会发出声音吗? It doesn't matter because there is no way to write a valid C program that can tell the difference. 没关系,因为没有任何方法可以编写有效的C程序来说明差异。 This means that it would be pointless for the standard to define this. 这意味着标准对此没有意义。 All we need to know is that by the time any code runs variables with static storage duration have been initialized. 我们需要知道的是,到任何代码运行时,具有静态存储持续时间的变量都已初始化。 The C11 standard draft spells it out in section 5.1.2: C11标准草案在5.1.2节中进行了详细说明:

All objects with static storage duration shall be initialized (set to their initial values) before program startup. 程序启动前,所有具有静态存储持续时间的对象都应初始化(设置为其初始值)。 The manner and timing of such initialization are otherwise unspecified. 否则未指定这种初始化的方式和时间。

In C++ on the other hand, things aren't that easy. 另一方面,在C ++中,事情并非那么简单。 It is possible to observe the order of initialization during dynamic initialization. 在动态初始化期间可以观察初始化的顺序。 In the standard draft we find section 3.6.2. 标准草案中,我们找到了3.6.2节。 It quickly gets complicated. 它很快变得复杂。 It defines the order as: first we do static initialization (this is equivalent to the only thing C can do) and after that dynamic initialization is done. 它将顺序定义为:首先我们进行静态初始化(这等效于C可以做的唯一事情),然后完成动态初始化。 So far so good. 到现在为止还挺好。 We get to this part: 我们到这一部分:

Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit. 在单个转换单元中定义了有序初始化的变量,应按其在转换单元中定义的顺序进行初始化。

and everything is still ok in the world. 而且世界上一切都还好。 But then things quickly fall apart: 但是事情很快就崩溃了:

An implementation is permitted to perform the initialization of a non-local variable with static storage duration as a static initialization even if such initialization is not required to be done statically 允许实现以静态存储持续时间执行非局部变量的初始化作为静态初始化,即使这种初始化不需要以静态方式完成

This sentence moves us from a predictable world to "it's complicated". 这句话使我们从一个可以预见的世界转向“它很复杂”。 The code example in that section of the standard explains this perfectly: 标准的该部分中的代码示例对此进行了完美解释:

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

In short, in C it doesn't matter, in C++ if you write code that depends on this you'll quite likely to run into trouble when you change compilers. 简而言之,在C语言中没关系,在C ++中,如果编写依赖于此的代码,则在更改编译器时很可能会遇到麻烦。

So your quote is doubly incorrect. 因此,您的报价是双重错误的。 Not only isn't initialization done in order of declaration (it's static first, then dynamic), it's also quite fuzzy what is actually static and what is dynamic. 初始化不仅没有按照声明的顺序进行(先是静态,然后是动态),而且实际上是静态的还是动态的也很模糊。

In C++ the order of initialisation has to be defined, since there may be constructors which are called in the initialisation of a variable. 在C ++中,必须定义初始化的顺序,因为可能存在在变量的初始化中调用的构造函数。 Thus C++ defines in which order this code is executed. 因此,C ++定义了此代码的执行顺序。 In plain C there are no constructors. 在普通C中,没有构造函数。 There is no way to tell in which order the variables are initialised, as long as each variable gets initialised before any code that can access the variable is executed. 只要在执行任何可以访问该变量的代码之前就初始化每个变量,就无法确定变量的初始化顺序。

The C standard (C11) 6.7.6 says C标准(C11)6.7.6说

A full declarator is a declarator that is not part of another declarator. 完整声明符是不属于另一个声明符的声明符。 The end of a full declarator is a sequence point. 完整声明符的末尾是一个序列点。

Meaning that at the end of each declaration, the initialization must be done and all sub-expressions must have been evaluated for side effects. 这意味着在每个声明的末尾,必须完成初始化并且必须对所有子表达式进行副作用评估。

When the actual code is executed isn't specified. 未指定实际代码的执行时间。 Meaning it could be done long before the line where the initialization takes place, but not after that line. 这意味着可以在进行初始化的行之前很长时间完成,但不能在该行之后完成。

Variables with static storage duration is a special case, since they are guaranteed to be initialized before program startup. 具有静态存储持续时间的变量是一种特殊情况,因为可以保证在程序启动之前对其进行初始化。 Their order of execution wouldn't matter in C, since they can't depend on each other (must be initialized to constant expressions). 它们的执行顺序在C语言中无关紧要,因为它们彼此不依赖(必须初始化为常量表达式)。

In C++, class objects with static storage duration are initialized in an unspecified order and therefore they shouldn't be written so that they rely on each other to be initialized in a certain order. 在C ++中,具有静态存储持续时间的类对象以未指定的顺序初始化,因此不应编写它们,以便它们彼此依赖以特定的顺序进行初始化。

Also please note 6.7.9/23: 另请注意6.7.9 / 23:

The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified. 初始化列表表达式的求值相对于彼此不确定地排序,因此未指定发生任何副作用的顺序。

Meaning that we can't know the order in which all initializers part of the same declaration are executed. 这意味着我们不知道执行同一声明的所有初始化程序部分的顺序。

I believe C and C++ are identical in all of the above, though C++ will also execute constructors as part of the initialization. 我相信C和C ++在上述所有方面都是相同的,尽管C ++还将在初始化过程中执行构造函数。

暂无
暂无

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

相关问题 在C ++标准中它说的是什么:: delete可以改变左值? - Where in the C++ Standard does it say ::delete can change lvalues? C++ 标准对堆栈溢出有何规定? - What does the C++ standard say about stack overflow? 在C ++标准中它表示必须初始化const内置类型变量的定义? - Where in the C++ Standard does it say that the definition of a const built-in type variable must be initialized? 数字和字段宽度的格式化输出,C ++标准对此有何说明? - formatted output of a number and field width, where does the C++ standard say about it? 在C ++标准中,它表示sizeof(wchar_t)<= sizeof(long)和sizeof(bool)<= sizeof(long)? - Where in the C++ Standard does it say that sizeof(wchar_t) <= sizeof(long) and sizeof(bool) <= sizeof(long)? C++ 标准究竟在哪里说取消引用未初始化的指针是未定义的行为? - Where exactly does C++ standard say dereferencing an uninitialized pointer is undefined behavior? 标准中的哪个地方表示声明`auto f()() - &gt; int;`是不允许的? - Where in the Standard does it say that the declaration `auto f()() ->int;` is not allowed? 标准中哪里说下面的 typedef 是有效的? - Where in the standard does it say that the typedef below is valid? 在标准(C ++ 14)中它表示以下两个声明是等效的吗? - Where in the Standard (C++14) does it say that the following two declarations are equivalent? 在C ++ 14 Standard中,它表示非constexpr函数不能用于constexpr函数的定义吗? - Where in C++14 Standard does it say that a non-constexpr function cannot be used in a definition of a constexpr function?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM