我正在尝试理解常量表达式概念(来自c++reference):
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
为什么S::c
不是常量表达式,直到我们定义它。它被声明为静态 const 数据成员,但是......
答案 0 :(得分:4)
引用C ++ 11标准的相关部分(草案N3337),第5.19节,第2段:
条件表达式是核心常量表达式,除非它涉及以下之一作为潜在评估的子表达式(3.2),但是逻辑AND(5.14),逻辑OR(5.15)和条件(5.16)操作的子表达式未考虑不被考虑[注意:重载运算符调用函数。 - 结束说明]:
左值 - 右值转换(4.1),除非它适用于
- 一个整数或枚举类型的glvalue,它引用一个带有前面初始化的非易失性const对象,用一个常量表达式初始化
S::c
的定义中没有d
的先前初始化。
编辑:为什么会这样:
5.1.1/8
:S::c
是一个左值。3.10/1
:glvalue是左值或x值。5/8
:指定只要使用需要prvalue的运算符,就会发生左值到右值的转换。答案 1 :(得分:2)
按顺序......
constexpr int d = 10 * S::c;
const int S::c = 5;
...编译S::c
值时,d
的值尚未知晓。但是尝试交换这些行:
const int S::c = 5;
constexpr int d = 10 * S::c;
答案 2 :(得分:1)
在C ++编译过程中的其他初始化之前执行常量初始化。在该示例中,d
的常量初始化保证在S::c
的常量初始化之前发生。常量表达式必须仅由常量值组成。初始化d
时,S::c
已知为常量值,因此表达式不会被视为常量。