Cur*_*ous 10 c++ language-lawyer c++14 c++17
struct S {
static const int c;
};
const int d = 10 * S::c; // not a constant expression: S::c has no preceding
// initializer, this initialization happens after const
const int S::c = 5; // constant initialization, guaranteed to happen first
Run Code Online (Sandbox Code Playgroud)
为什么初始化d不是常量表达式(因此不是常量初始化过程的一部分)?注释似乎是因为它使用的值没有前面的初始值设定项,但似乎没有在条件列表中提及将表达式限定为常量表达式(这里列出了条件) .特别是哪些条件限定某些东西是一个常量表达式,它是否违反了?
如果它与必须在编译时评估常量初始化这一事实有关,那么标准提到恒定初始化不需要在编译时发生,甚至可能发生在例如加载时间.那为什么不只是c在编译时初始化而只是d在加载时?(我可能会把自己想成一个圈子)
感谢Jayesh我能够找到一个类似的问题"令人惊讶"的常量初始化,因为定义顺序,但答案似乎是谈论左值转换的左值,这里左值转换的左值是多少?除此之外,标准中没有引用关于这里违反了哪些条件.答案也没有解释为什么初始化不会分解为加载时和编译时.
根据标准\xc2\xa76.6.2/p2 静态初始化 [basic.start.static]:
\n\n\n\n\n如果具有静态或线程存储持续时间的变量或临时对象由实体的常量初始值设定项初始化,则执行常量初始化。
\n
d现在,在初始化时,编译器发现c尚未静态初始化(即尚未定义)。因此, 的初始化器d不符合常量表达式的条件,因此 的初始化d符合动态初始化的条件。因为静态初始化发生在动态初始化之前,c所以将在 之前初始化d,因此在 's 时初始化d。初始化c已经初始化,因此代码是有效的。
现在,如果您更改初始化的顺序或c内联初始化,则 的初始化程序d有资格作为常量表达式,因为编译器在 的初始化时d已经看到了 的静态初始化c(即,c)。
现在,为什么在第一种情况下 的初始化器不是常量表达式的答案由\xc2\xa78.20/p2 常量表达式 [expr.const]d给出(重点是我的):
\n\n\n2表达式 e 是核心常量表达式,除非 e 的计算遵循抽象机 (4.6) 的规则,\n 将计算以下表达式之一:
\n\n...
\n\n2.7 \xe2\x80\x94 左值到右值的转换(7.1),除非它应用于
\n\n2.7.1 \xe2\x80\x94 整型或枚举类型的非易失性泛左值,指的是具有前面的初始化的完整非易失性 const 对象,用常量表达式初始化。
\n
在表达式 10 * c 中,c 没有预先初始化,因此不是常量表达式。
\n