constexpr说明符性能不符合我对C++的期望

Gor*_*don 2 c++ compiler-optimization visual-studio c++11 c++14

我刚刚了解到constexpr说明符函数可以在编译过程中运行,我试着用Debug x86 Mode检查VS 2017的实际性能,结果显示它们之间的时间差很小.它仍然耗费了很多时间而不是"0".我做错了什么,任何人都可以帮助我,非常感谢!

#include <iostream>
#include <time.h>

size_t r_fun(size_t n) noexcept
{
    if (n == 0) return 0;
    if (n == 1) return 1;
    return r_fun(n - 1) + r_fun(n - 2);
}

constexpr size_t c_fun(size_t n) noexcept
{
    if (n == 0) return 0;
    if (n == 1) return 1;
    return c_fun(n - 1) + c_fun(n - 2);
}


int main()
{
    clock_t start, finish;

    start = clock();
    auto r_x = r_fun(40);  
    finish = clock();
    std::cout <<"result:"<< r_x<< "\ttime:" << (double)(finish - start) << std::endl;

    start = clock();
    static const auto c_x = c_fun(40);
    finish = clock();
    std::cout << "result:" << c_x << "\ttime:" << (double)(finish - start) << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

lll*_*lll 7

您的constexpr函数需要在编译器中进行太多计算,这就是编译器选择将其延迟到运行时执行的原因.

你可以改变这一行:

static const auto c_x = c_fun(40);
Run Code Online (Sandbox Code Playgroud)

至:

constexpr auto c_x = c_fun(40);
Run Code Online (Sandbox Code Playgroud)

看看编译器的输出.在clang上,它告诉我:

note: constexpr evaluation hit maximum step limit;
Run Code Online (Sandbox Code Playgroud)

c_x确实是一个编译时常量,但由于实现限制,编译器无法计算它.请注意,您的函数具有指数复杂性.

如果你改变40到一些合理的数字,比如10,一切都会好的:

constexpr auto c_x = c_fun(10);
Run Code Online (Sandbox Code Playgroud)

  • @WhozCraig对于clang,这个限制不能被选项覆盖,`-fconstexpr-steps`选项是`int`类型,这个函数需要`long`步骤.https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/CompilerInvocation.cpp#L2464.但总而言之,它依赖于实现. (3认同)
  • 即使在40岁时,编译器也可以毫无问题地解决这个问题.[g ++ 8.1](https://godbolt.org/z/dnAer-)例如,显然减少到最终答案.这一切都取决于你正在使用的工具链以及它所施加的限制. (2认同)