繁体   English   中英

为什么半初始化结构的 constinit 不起作用

[英]Why constinit of half-initialized struct does not work

struct A1 { int x;     int y; };
struct A2 { int x = 1; int y = 2; };
struct A3 { int x = 1; int y; };

constinit A1 a1; // x == 0, y == 0.
constinit A2 a2; // x == 1, y == 2.
          A3 a3; // x == 1, y == 0.
constinit A3 a4; // Error: illegal initialization of 'constinit' entity with a non-constant expression

int main() {}

a4有什么问题? 我的意思是a4.x应该由常量1初始化(与它工作的a2相同)和a4.y由常量0初始化,因为a4是全局 static 变量(与它工作的a1相同)。

现在,考虑到 MSVC 和 GCC 都无法编译这段代码,我假设标准以某种方式禁止它。 但无论如何我看a4它的初始值是准确的,常量并且在编译时已知所以为什么标准禁止我们将它声明为constinit )?

除此之外, clang++还拒绝了第一个constinit ialization:

error: variable does not have a constant initializer
constinit A1 a1;  // x == 0, y == 0.

我认为在这种情况下,我们可能会遗漏一些措辞。

首先,初始化分为三个阶段( [basic.start.static] ):

  1. 常量初始化
  2. 如果不是那样,则零初始化(对于 static 存储持续时间变量,如本问题中的变量)
  3. 如有必要,动态初始化

(1) 和 (2) 一起是 static 初始化,(3) 是……好吧,动态的。 constinit所做的是确保没有来自[dcl.constinit]的动态初始化:

如果用constinit说明符声明的变量具有动态初始化 ([basic.start.dynamic]),则程序格式错误。

常量初始化规则来自[expr.const]

变量或临时 object o常量初始化的,如果

  • 它要么有一个初始化器,要么它的默认初始化导致执行一些初始化,并且
  • 当解释为常量表达式时,其初始化的完整表达式是一个常量表达式,除非o是 object,该完整表达式也可以为o及其子对象调用 constexpr 构造函数,即使这些对象是非文字的class 种。

话虽如此,让我们通过三种类型来了解 go。 从最简单的开始:

struct A2 { int x = 1; int y = 2; };
constinit A2 a2; // x == 1, y == 2.

在这里,我们正在初始化所有成员,这显然是常量初始化。 这里不是一个真正的问题。

下一个:

struct A1 { int x;     int y; };
constinit A1 a1; // x == 0, y == 0.

在这里,我们的默认构造函数没有...什么都没有,没有初始化。 所以这不是常量初始化。 但是零初始化发生了,然后就没有进一步的初始化了。 这里肯定没有必须进行的动态初始化,所以constinit没有什么可以诊断的。

最后:

struct A3 { int x = 1; int y; };
constinit A3 a4; // Error: illegal initialization of 'constinit' entity with a non-constant expression

在采用P1331之前, a4的这种初始化显然不是常量初始化,因为常量初始化明确需要完全初始化的变量。 但是我们不再有这个要求了,规则后来被移动了 - 到实际读取a4.y的时候。

但我认为在这种情况下的意图是a4不是常量初始化,因为它部分未初始化。 这可能值得一个核心问题。

鉴于不是常量初始化,那么我们把go改成零初始化。 但在那之后, a4仍然没有完全初始化——因为我们必须将x设置为1 没有提供半常数半零初始化。 规则是不变的,或者如果不是那样,则为零。 由于这不是(或者至少不应该是)常量初始化,并且零初始化是不够的,因此a4必须进行动态初始化。 因此, constinit应该标记这种情况。 gcc 和 msvc 在这里是正确的(clang 错误地拒绝a1 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM