非局部非内联变量的初始化:它是否严格在调用main()函数之前进行? [英] The initialization of non-local non-inline variables: does it take place strictly before the `main()` function call?
问题描述
在以下简单的程序实现中,数字的打印顺序是定义的吗?
Is the order in which digits will be printed in the following simple program implementation-defined?
#include <iostream>
struct Foo
{
Foo()
{
std::cout << "1" << std::endl;
}
};
Foo foo;
int main()
{
std::cout << "2" << std::endl;
}
标准中的一些措辞( 非动态初始化局部变量 [basic.start.dynamic]/4 ):
Some wordings from the standard (Dynamic initialization of non-local variables [basic.start.dynamic]/4):
由实现定义的是,具有静态存储持续时间的非局部非内联变量的动态初始化是在
main
的第一条语句之前排序还是推迟.如果将其推迟,则很可能在未初始化odr使用与要初始化的变量在同一转换单元中定义的任何非内联函数或非内联变量之前发生.*
It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of
main
or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized.*
...
*)在这种情况下,将初始化具有静态存储持续时间且具有副作用初始化的非局部变量,即使该变量本身并未被odr使用([basic.def.odr],[basic.stc.static] ).
*) A non-local variable with static storage duration having initialization with side effects is initialized in this case, even if it is not itself odr-used ([basic.def.odr], [basic.stc.static]).
并且 main()
函数未使用过.
And the main()
function is not odr-used.
推荐答案
允许的输出为1/2、2和2/1.
The permitted outputs are 1/2, 2, and 2/1.
如果不延迟变量foo
的初始化 ,则在main
的开始之前对它进行排序,因此在2
之前打印1
.
If initialization of the variable foo
is not deferred, then it is sequenced before the start of main
, so 1
is printed before 2
.
If the initialization is deferred, then the requirement is that initialization of foo
must happen before any (other) odr-use of foo
. It does not say that no initialization must happen if there is no odr-use. The output 2/1 would definitely be very odd for this example (and the output 2 the only one used in practice by implementations which defer initialization), but I don't see anything in the standard that strictly rules it out.
我相信标准中措辞的原因是它允许实现使用一种防护来推迟翻译单元中所有此类变量的初始化.如果我们这样修改您的示例:
I believe the reason for the wording in the standard is that it allows implementations to use one guard for deferring the initialization of all such variables in a translation unit. If we amend your example like this:
…
Foo foo;
struct Bar {
Bar() { std::cout << "3\n"; }
void Use() {}
} bar;
int main()
{
std::cout << "2" << std::endl;
bar.Use();
}
使用单个保护并延迟初始化,即使程序中没有foo
的odr-use(除初始化之外)功能,foo
也会与bar
一起初始化.在这种情况下,也需要保持一致性,因为该示例使用有序初始化,因此必须在bar
之前对foo
进行初始化,因此,唯一允许的输出为1/3/2(无延迟初始化)和2/1/3(延迟初始化).但是,如果我们使用其他构造来获得无序初始化,则实现也可能会生成2/3/1
(同样,也不会使用foo
进行非初始化odr).
With a single guard and deferred initialization, foo
would be initialized along with bar
, even though there is no odr-use (besides initialization) of foo
in the program. In this case, it is also required for consistency because the example uses ordered initialization, so the initialization of foo
must be sequenced before bar
, so the only permitted outputs are 1/3/2 (no deferred initialization) and 2/1/3 (deferred initialization). But if we used a different construct to obtain unordered initialization, an implementation might also produce 2/3/1
(again, with no non-initialization odr-use of foo
).
这篇关于非局部非内联变量的初始化:它是否严格在调用main()函数之前进行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!