微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

'const' 限定符何时保证变量是常量表达式?

如何解决'const' 限定符何时保证变量是常量表达式?

据我所知,C++ 中的 const 限定符基本上声明了内部链接,有时它允许将变量用作常量表达式,以便将其放入数组边界、切换案例等.

但显然情况并非总是如此,我不知道如何正确使用 constconstexpr

具体来说,我发现当在数组边界中使用 const 限定数组的元素时,它不会被视为常量表达式,如下面的代码所示。

const int N = 3;
int foo[N] = {1,2,3};  // Valid

const int bar[5] = {1,3,4,5};
int arr[bar[2]] = {1,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,但这会破坏现有代码,因此不会更改。


究竟需要什么才能使表达式保持不变?

这很有趣,因为该语言实际上并没有说明表达式需要什么才能成为常量表达式。相反,它假定 所有 表达式都是常量表达式,并提供一个条件列表,如果不满足这些条件,则表达式将不是常量表达式。

规则是here

表达式 E 是核心常量表达式除非对 E 的求值,遵循抽象机 ([intro.execution]) 的规则,将求值以下之一:...

然后是一个条件列表,这些条件使表达式不是常量表达式。

,

使用 const 声明 const int bar[5] = {1,2,3,4,5}; bar[2] 被视为变量而不是常量。

使用 constexpr 声明 constexpr int bar[5] = {1,5}; bar[2] 被视为预期的常量

相反,对于纯整型constconstexpr 声明都作为常量受到威胁。

这是因为语言规则。

对于 example,如果您查看为 const int bar[5] = {1,5};constexpr int bar[5] = {1,5}; 生成的汇编代码, 可以看出它们是相同的。所以从技术上讲,两者都行得通。

因此,这验证了限制来自语言规则,如其他一些答案所述,这些限制有一些历史原因。

,

完全符合标准

在后面的部分使用 constexpr 而不是 const 可以解决问题。

因为 constexpr 在编译时计算值

但为什么最后一条语句无效?

const int bar[5] = {1,5}; 

表示 bar 中的值是在运行时计算的常量值


int arr[bar[2]] = {1,3};  

在这里,您是在编译时进行此检查。所以 const 抛出错误。使用 constexpr 解决它,因为它在编译时推导它。

究竟需要什么才能使表达式保持不变?

向表达式声明 const 会告诉编译器将该值视为 const 并且不允许程序员修改它。 const 和 constexpr 都可以达到目的,但声明使编译器将初始化推迟到运行时。当编译器在编译时检查 int arr[bar[2]] 中的 const 值时,它会抛出错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。