非局部非内联变量的初始化:它是否严格在调用main()函数之前进行? [英] The initialization of non-local non-inline variables: does it take place strictly before the `main()` function call?

查看:84
本文介绍了非局部非内联变量的初始化:它是否严格在调用main()函数之前进行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下简单的程序实现中,数字的打印顺序是定义的吗?

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.

如果推迟初始化,则要求foo的初始化必须在任何(其他)

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆