'const'限定符何时保证变量是常量表达式?
据我所知,constC++中的限定符基本上声明了内部链接,有时它允许将变量用作常量表达式,以便将其放入数组边界、切换案例等。
但显然情况并非总是如此,我对const和的正确用法一无所知constexpr。
具体来说,我发现当在数组边界中使用 const 限定数组的元素时,它不会被视为常量表达式,如下面的代码所示。
const int N = 3;
int foo[N] = {1, 2, 3}; // Valid
const int bar[5] = {1, 2, 3, 4, 5};
int arr[bar[2]] = {1, 2, 3}; // Invalid because a VLA can't be initialized
在后面的部分使用constexpr而不是const解决问题。但是为什么最后一条语句无效呢?究竟需要什么才能使表达式保持不变?
回答
唯一一次const与constexpr变量声明中的含义相同,即变量是整数或枚举类型时。另外,这个变量声明的初始化器必须是一个常量表达式。例如
const int n = 42; // same as constexpr
// type is int
// initializer is integer literal, which is constant expression
std::cin >> x; // some user input
const int n = x; // NOT constexpr
// because initializer is not a constant expression
const double n = 4.2; // NOT constexpr
// type is not integral or enumeration type
您的最后一行代码无法编译,因为bar它不是整数或枚举类型,因此它不是constexpr. 由于它的constexpr任何元素都不constexpr是,因此它们不能用作数组绑定。
整数这种特殊情况的原因是历史性的:数组边界需要是常量表达式,但在 C++11 之前,表达它的唯一方法是使用const int. 从技术上讲,可以更改规则以要求声明具有,constexpr但这会破坏现有代码,因此不会更改。
究竟需要什么才能使表达式保持不变?
这很有趣,因为该语言实际上并没有说明表达式需要什么才能成为常量表达式。相反,它假定所有表达式都是常量表达式,并提供一个条件列表,如果不满足这些条件,则表达式将不是常量表达式。
规则在这里:
表达式 E 是核心常量表达式,除非E 的计算遵循抽象机 ([intro.execution]) 的规则,将计算以下之一: ...
这后面是一个条件列表,这些条件使表达式不是常量表达式。
- @morimn An element of an `int` array is definitely an `int` type, you're right about that. It's just that the rules about what makes a `const` variable a `constexpr` variable is very strict, and it doesn't apply for `int[]` even though it applies for `int`.