是 int x = x; 在 C++ 中定义良好?

Jan*_*tke 1 c++ initialization global-variables language-lawyer

我有以下代码:

// in global scope:
int x = x;
Run Code Online (Sandbox Code Playgroud)

此代码编译时不会对 GCC 和 clang发出警告:

x:
  .zero   4
Run Code Online (Sandbox Code Playgroud)

这是明确定义的吗?它是如何工作的?

Jan*_*tke 7

是的,这是明确定义的,相当于:

int x = 0;
Run Code Online (Sandbox Code Playgroud)

如果x是局部变量,那么您的代码将是 UB,因为x将在其生命周期开始之前访问。但是,全局变量的情况并非如此,因为:

如果具有静态或线程存储持续时间的变量或临时对象是常量初始化的,则执行常量初始化。如果不执行常量初始化,则具有静态存储持续时间或线程存储持续时间的变量将被零初始化零初始化和常量初始化一起称为静态初始化;所有其他初始化都是动态初始化。所有静态初始化都强烈发生在任何动态初始化之前。

- [基本.开始] p2

int x不是常量初始化的,因为x不是常量表达式。因此,它是零初始化的,并且这种情况强烈发生在任何动态初始化之前。

这告诉我们这int x = x;相当于:

int x = 0;
// assume this is called at some point before main():
void __dynamic_init__() {
   x = x;
}
Run Code Online (Sandbox Code Playgroud)

现在明显的问题是:

如果这是执行动态初始化,为什么编译器不输出看起来像动态初始化的代码,而只是发出.zero 4

一种解释是动态初始化可以根据“假设规则”进行优化。另一种解释是这样的:

允许实现将具有静态或线程存储持续时间的变量初始化作为静态初始化,即使不需要静态完成此类初始化,前提是:

  • (3.1) 初始化的动态版本不会更改其初始化之前的任何其他静态或线程存储持续时间对象的值,并且
  • (3.2) 如果所有不需要静态初始化的变量都被动态初始化,静态版本的初始化在初始化变量中生成的值与动态初始化生成的值相同。

- [基本.开始] p3

(3.1) 显然是正确的,因为表达式x不修改任何对象。(3.2) 也是正确的,因为如果int x动态初始化,则表达式x将始终为零。

因此,这种动态初始化也可以变成静态初始化为零。


关于生命周期的注释 - 可能的措辞问题

根据[basic.life] p1.2,对象的生命周期从“初始化(如果有)完成”开始。

目前尚不清楚 的生命周期是x在零初始化之后开始,还是在动态初始化之后开始。如果它在动态初始化之后开始,则动态初始化期间的表达式将在其生命周期开始之前x访问,这是未定义的行为。x

然而,由于静态初始化是初始化的一种形式,这看起来更像是一个措辞问题,而不是预期的行为。毕竟,本段根本不承认发生了多次初始化。

  • 关于“零初始化是否开始生命周期” - 似乎未指定,与非规范注释相矛盾:/sf/ask/4759384661/那么动态地 (2认同)

归档时间:

查看次数:

103 次

最近记录:

2 年,6 月 前