C ++ constexpr实现差异

时间:2018-10-28 22:44:12

标签: c++ g++ c++14 constexpr clang++

只是了解了 constexpr 函数,然后去了 godbolt 来了解编译器如何优化代码,并发现编译器的行为完全不同。

具有以下代码:

constexpr int square(int num) {
    return num * num;
}

int main() {
    int a = square(2);
}

g ++ icc 编译器计算函数结果并将其分配给变量(如我所料),但是 msvc clang 调用功能。

要使用优化,我们应该执行其他步骤:

constexpr int square(int num) {
    return num * num;
}

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

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

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

1 个答案:

答案 0 :(得分:3)

所有编译器都是正确的。

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

假装没有as-if rule,我们可以说当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请求的变量,因此不需要编译时值。

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

第二版

 constexpr int c = square(2);

square()变量请求constexpr值,因此所有编译器必须计算square(2)编译时(他们可以这样做,因为{ {1}}是一个已知的编译时值。