我们如何理解关于 constexpr 的“如果可能”
Posted
技术标签:
【中文标题】我们如何理解关于 constexpr 的“如果可能”【英文标题】:How do we understand "if possible" about constexpr 【发布时间】:2021-09-24 03:00:24 【问题描述】:我已经阅读了关于constexpr
的链接:https://en.cppreference.com/w/cpp/language/constexpr
它表示 constexpr 说明符声明可以在编译时评估函数或变量的值。
据我了解,这意味着constexpr
指定的变量可能会或可能不会在编译时进行评估。
This link 告诉我同样的事情:constexpr 变量不是编译时值。
但是,我做了一个测试,让我很困惑:https://godbolt.org/z/9ajb4xKK8
如您所见,变量a
必须在编译时求值,否则不能用于声明数组。而变量s
不能被constexpr
指定,因为std::string
的构造函数不能在编译时调用。
总之,这个测试似乎告诉我constexpr
必须在编译时评估该值。不然怎么用a
这个变量来声明数组呢?
我理解错了什么?
编辑
我知道constexpr
函数可以在运行时或编译时调用。例如,如果我们将运行时参数传递给constexpr
函数,该函数将在运行时被调用,我理解。
但似乎必须在编译时评估 constexpr
变量。我可以说任何constexpr
变量都必须在编译时进行评估吗?
【问题讨论】:
您发现了一个示例,其中constexpr
必须在编译时出现。还有其他示例可以在运行时使用。
@463035818_is_not_a_number 我知道constexpr
函数可以在运行时或编译时调用。但我不明白如何在运行时而不是在编译时评估 constexpr
变量。如您所见,如果constexpr
变量无法在编译时求值,例如std::string s
,则会产生错误。那么为什么我们不能说必须在编译时评估 constexpr
变量呢?
我认为constinit
更符合您的预期。据我了解,constexpr
更明确和更具表现力。考虑您想在需要编译时间常数的上下文中使用x
,您可以编写const int x = foo();
,这在任何情况下都可以,但稍后在需要编译时间常数的上下文中使用x
可能会失败,具体取决于foo
。另一方面,当foo
不是 constexpr 时,constexpr int x = foo();
会提前失败
cppreference 是为了“简化”标准而编写的,正式定义见dcl.constexpr。
constexpr 变量仅是编译时,而 constexpr 函数是编译或运行时取决于上下文。
【参考方案1】:
首先,godbolt 链接中使用的编译器 (gcc 11.1) 允许可变长度数组。所以a
not 必须是一个常量表达式。即下面的这个sn-p代码将被接受
int a = 5;
int arr[a];
但是当你确实需要某个常量表达式时,constexpr
将允许你使用其中的变量/函数。
constexpr - 指定变量或函数的值可以出现在>常量表达式
中
例如,当您使用std::array
模板创建数组时,大小必须是常量
所以这样做是不行的
int a = 5;
std::array<int, a> arr;
另一方面,constexpr
允许在常量表达式中使用a
,因此您可以这样做
constexpr int a = 5;
std::array<int, a> arr;
【讨论】:
以上是关于我们如何理解关于 constexpr 的“如果可能”的主要内容,如果未能解决你的问题,请参考以下文章