变量和函数在全局范围内的递归依赖
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。
... 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.
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.
我正在使用我的 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
初始化为零来打破这个循环。
这让我很惊讶。根据标准,这是正确的行为还是我在这里调用了一些未定义的行为?
... 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.
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.