了解常量表达式

Understanding constant expression

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

在这个序列中……

constexpr int d = 10 * S::c;
const int S::c = 5;

…编译d值时,S::c的值还不知道。但是尝试交换这些行:

const int S::c = 5;
constexpr int d = 10 * S::c;

引用 C++11 标准(草案 N3337)的相关部分,第 5.19 节,第 2 段:

A conditional-expression is a core constant expression unless it involves one of the following as a potentially evaluated subexpression (3.2), but subexpressions of logical AND (5.14), logical OR (5.15), and conditional (5.16) operations that are not evaluated are not considered [ Note: An overloaded operator invokes a function. — end note ]:

  • an lvalue-to-rvalue conversion (4.1) unless it is applied to

    • a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression

在你定义的 d 中没有预先初始化 S::c

编辑:为什么适用:

  • 5.1.1/8: S::c 是一个左值。
  • 3.10/1: glvalue 是左值或 xvalue。
  • 5/8:指定只要使用需要纯右值的运算符,就会发生左值到右值的转换。
  • 证明乘法需要一个纯右值让我很头疼。它在很多地方都有暗示,但我没有找到任何地方明确

常量初始化在C++编译过程中先于其他初始化进行。在示例中,d 的常量初始化保证在 S::c 的常量初始化之前发生。常量表达式必须完全由常量值组成。初始化 d 时,已知 S::c 是常量值,因此表达式不被视为常量。