C++constexpr实现差异

C++ constexpr realization differencies

本文关键字:实现 C++constexpr      更新时间:2023-10-16

刚刚了解了constexpr函数,并访问godbolt了解编译器如何优化代码,发现编译器的行为截然不同。

具有以下代码:

constexpr int square(int num) {
return num * num;
}
int main() {
int a = square(2);
}

g++icc编译器计算函数结果并将其分配给一个变量(正如我所期望的(,但msvcclang调用函数。

要使用优化,我们应该做额外的步骤:

constexpr int square(int num) {
return num * num;
}
int main() {
constexpr int c = square(2);
int a = c;
}

对这种行为有什么合理的解释吗?

链接到导螺杆示例:https://godbolt.org/z/ez7luu

所有编译器都是正确的。

constexpr函数是一个可以在编译时或运行时根据情况计算的函数。

假设没有"好像"规则,我们可以说,当constexpr函数的结果到达某个被请求为已知编译时间的地方时,编译器必须计算编译时间。

例如,阵列的大小

int  a[square(10)];

或模板参数

std::array<int, square(10)>  a;

constexpr可变

constexpr int  a { square(10) };

在某些情况下,函数必须在运行时计算,就像接收运行时已知的输入值一样;例如

int a;
std::cin >> a;
int b { square(a) }; 

否则,编译器可以选择是在编译时还是在运行时计算该值。

在您的第一个版本中

int a = square(2);

我们在编译器中可以选择区域,因为2是已知的编译时间,所以编译器可以选择编译时间计算,但该值是为非constexpr变量请求的,所以不需要编译时间值。

您可以看到,两个编译器正在计算编译时,另外两个编译器在运行时。通常,这种行为在很大程度上取决于优化级别。事实上,在您的示例中将-O2添加到编译标志后,所有编译器都会产生不同的输出。

在您的第二个版本中

constexpr int c = square(2);

constexpr变量需要square()值,因此所有编译器都必须计算square(2)编译时间(而且他们可以这样做,因为2是已知编译时间的值(。