以下代码无法编译live on Ideone:
#include <iostream>
using namespace std;
int main() {
const double kPi = 3.14;
constexpr double kPi2 = 2.0*kPi;
cout << kPi2;
}
错误消息是:
prog.cpp: In function 'int main()': prog.cpp:6:30: error: the value of 'kPi' is not usable in a constant expression constexpr double kPi2 = 2.0*kPi; ^ prog.cpp:5:15: note: 'kPi' was not declared 'constexpr' const double kPi = 3.14;
用const
,it compiles successfully代替kPi
constexpr
声明。
另一方面,当使用int
代替double
时,似乎const
plays well与constexpr
:
#include <iostream>
using namespace std;
int main() {
const int k1 = 10;
constexpr int k2 = 2*k1;
cout << k2 << '\n';
return 0;
}
为什么int
和double
使用constexpr
初始化const
会有不同的处理方法?
这是Ideone编译器中的错误吗?这是C ++标准所要求的吗?那是为什么?
上面的代码是UB吗?
P.S。我尝试使用Visual Studio 2015 C ++编译器,它编译了第一个代码段(用constexpr
初始化const
)就好了。
答案 0 :(得分:1)
对于要在编译时计算的constexpr,在该constexpr的初始化中使用的所有内容也必须在编译时计算。 如果将某些内容声明为const,则并不意味着该值将在编译时可用。
执行以下行:
const double dbl = 2.;
该标准未指定double
的表示形式,因此OS必须对此进行处理。因此,当您的程序由OS加载时,二进制文件中会包含一个特殊的汇编子例程,该子例程将使这种情况发生。
如果使用int
,则表示是由标准指定的,因此编译器将知道如何使用它。但是,也可以通过将double
设为constexpr
来实现相同的目的,因此编译器将在编译时对其进行计算。在这种情况下,double
也将是const
(您不能同时制作constexpr
就不能制造const
)。
这将起作用:
constexpr double kPi = 3.14;
constexpr double kPi2 = 2.0*kPi;
如果使用整数,则编译器将在编译时设置该const的值,以便constexpr可以工作。
请记住,在某些情况下,不同的编译器可以将const
解释为constexpr
并使其起作用。但这不是标准的一部分。
答案 1 :(得分:0)
Shafik Yaghmour已经提供link explaining the background。
由于我必须维护必须使用不同标准编译的代码,因此我使用以下宏:
#if __cplusplus <= 199711L // lower than C++11
#define MY_CONST const
#else // C++11 and above
#define MY_CONST constexpr
#endif
答案 2 :(得分:-3)
规则:“constexpr必须在编译时”进行评估。
让我们看下面的代码(通用示例);
const double k1 = size_of_array();
k1是常量,其初始化程序的值不知道编译时间,但其初始化程序在运行时间之前是已知的,因此k1不是常量表达式。因此,const变量不是constexpr。
但编译器会看到这些代码:
const int k1 = 10;
constexpr int k2 = 2*k1;
发生一个例外。 constexpr积分值可用于需要const整数的任何位置,例如模板参数和数组声明 [1]。
您可以从以下链接获取更多信息: