理解常量表达式

时间:2015-06-26 04:05:15

标签: c++ language-lawyer

我正在尝试理解常量表达式概念(来自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 数据成员,但是......

3 个答案:

答案 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/8S::c是一个左值。
  • 3.10/1:glvalue是左值或x值。
  • 5/8:指定只要使用需要prvalue的运算符,就会发生左值到右值的转换。
  • 证明乘法期望一个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已知为常量值,因此表达式不会被视为常量。