变量和函数在全局范围内的递归依赖

Recursive dependency of variable and function in global scope

我正在使用我的 C++ 编译器,我注意到全局变量的递归依赖性并且函数调用没有被拒绝。示例:

#include <iostream>

int foo();

int t = foo();

int foo()
{
    std::cout << "Hello before main: " << t << "\n";
    t = 10;
    return t + 10;
}

int main()
{
  std::cout << "Hello from main.\n";
}

此编译程序打印出以下内容:

Hello before main: 0
Hello from main.

因此,当我使用声明 t 时,它依赖于 foo 函数,后者又依赖于 t。 C++ 编译器通过在赋值表达式运行之前将 t 初始化为零来打破这个循环。

这让我很惊讶。根据标准,这是正确的行为还是我在这里调用了一些未定义的行为?

,对象的生命周期在其初始化完成时被认为开始;在访问它之前会导致 UB。

[basic.life]/1:

... The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • its initialization (if any) is complete (including vacuous initialization) ...

直到 C++20 这是明确定义的行为。 Zero initialization is performed at first for non-local variables.

As described in non-local initialization, static and thread-local variables that aren't constant-initialized (since C++14) are zero-initialized before any other initialization takes place. If the definition of a non-class non-local variable has no initializer, then default initialization does nothing, leaving the result of the earlier zero-initialization unmodified.

根据标准,[basic.start.static]/2

If constant initialization is not performed, a variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is zero-initialized ([dcl.init]). Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. All static initialization strongly happens before ([intro.races]) any dynamic initialization.