c++ - 当 constexpr 函数出错时会发生什么?

标签 c++ c++11 constexpr

我了解到 constexpr 函数在编译时求值。但是看看这个例子:

constexpr int fac(int n)
{
    return (n>1) ? n*fac(n-1) : 1;
}


int main()
{
    const int a = 500000;
    cout << fac(a);
    return 0;
}

显然这段代码会抛出错误,但由于 constexpr 函数是在编译时计算的,为什么我在编译和链接时没有看到错误?

进一步,我反汇编了这段代码,结果发现这个函数没有被评估,而是作为一个普通函数被调用:

(gdb) x/10i $pc
=> 0x80007ca <main()>:  sub    $0x8,%rsp
   0x80007ce <main()+4>:        mov    $0x7a11f,%edi
   0x80007d3 <main()+9>:        callq  0x8000823 <fac(int)>
   0x80007d8 <main()+14>:       imul   $0x7a120,%eax,%esi
   0x80007de <main()+20>:       lea    0x20083b(%rip),%rdi        # 0x8201020 <_ZSt4cout@@GLIBCXX_3.4>
   0x80007e5 <main()+27>:       callq  0x80006a0 <_ZNSolsEi@plt>
   0x80007ea <main()+32>:       mov    $0x0,%eax
   0x80007ef <main()+37>:       add    $0x8,%rsp
   0x80007f3 <main()+41>:       retq

但是,如果我像 fac(5) 这样调用:

constexpr int fac(int n)
{
    return (n>1) ? n*fac(n-1) : 1;
}


int main()
{
    const int a = 5;
    cout << fac(a);
    return 0;
}

汇编代码变成:

(gdb) x/10i $pc
=> 0x80007ca <main()>:  sub    $0x8,%rsp
   0x80007ce <main()+4>:        mov    $0x78,%esi
   0x80007d3 <main()+9>:        lea    0x200846(%rip),%rdi        # 0x8201020 <_ZSt4cout@@GLIBCXX_3.4>
   0x80007da <main()+16>:       callq  0x80006a0 <_ZNSolsEi@plt>
   0x80007df <main()+21>:       mov    $0x0,%eax
   0x80007e4 <main()+26>:       add    $0x8,%rsp
   0x80007e8 <main()+30>:       retq

fac 函数在编译时计算。

有人能解释一下吗?

编译命令:

g++ -Wall test.cpp -g -O1 -o test

以及 g++ 版本 7.4.0,gdb 版本 8.1.0

最佳答案

I learnt that constexpr functions are evaluated at compile time

不,constexpr 可以在编译时求值,也可以在运行时求值。

进一步阅读:

Apparently this code would throw an error

不,没有抛出任何错误。对于大输入,结果会溢出,这是未定义的行为。这并不意味着将抛出或显示错误。这意味着任何事情都可能发生。当我说什么的时候,我的意思是什么。该程序可能会崩溃、挂起、出现奇怪的结果、显示奇怪的字符或任何字面意思。

进一步阅读:

而且,正如 nathanoliver 指出的那样

when invoked in a constant expression, a constexpr function must check and error out on UB http://coliru.stacked-crooked.com/a/43ccf2039dc511d5

换句话说,编译时不能有任何UB。在运行时是 UB,在编译时是硬错误。

关于c++ - 当 constexpr 函数出错时会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57556474/

相关文章:

c++ - 在 Linux 中获取主板 deviceID 和 BIOS 序列号

c++ - OpenCV黑白视频空

c++ - QDeclarativeImageProvider 不在容器中加载图像

c++ - 为什么 clang 不警告从 double 到 int 的隐式转换,而是在从 long 到 int 时警告?

c++ - 返回从字符串文字创建的静态 string_view 是否安全?

c++ - 在Vector类对象上调用push_back()方法时收到错误

c++ - 不同 gcc 版本的 unordered_map 大小不同

c++ - 以下单例实现线程安全吗?

c++ - constexpr exp、log、pow

c++ - constexpr 数组作为模板非类型参数的 MSVC 错误