ahs*_*jfk 51 c++ recursion function constexpr
我一直在学习 C++constexpr函数,我实现了一个constexpr递归函数来找到第 n 个斐波那契数。
#include <iostream>
#include <fstream>
#include <cmath>
#include <algorithm>
#include <vector>
constexpr long long fibonacci(int num) {
if (num <= 2) return 1;
return fibonacci(num - 1) + fibonacci(num - 2);
}
int main() {
auto start = clock();
long long num = fibonacci(70);
auto duration = (clock() - start) / (CLOCKS_PER_SEC / 1000.);
std::cout << num << "\n" << duration << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
如果我constexpr从fibonacci()函数中删除标识符,则fibonacci(70)需要很长时间来评估(超过 5 分钟)。然而,当我保持原样时,程序仍然在 3 秒内编译,并在不到0.1几毫秒的时间内打印出正确的结果。
我了解到constexpr函数是在编译时计算的,所以这意味着fibonacci(70)编译器在不到 3 秒的时间内计算出来!但是,C++ 编译器比 C++ 代码具有更好的计算性能似乎不太正确。
我的问题是,在我按下“构建”按钮和编译完成之间,C++ 编译器是否真的评估了函数?还是我误解了关键字constexpr?
编辑:这个程序是g++ 7.5.0用--std=c++17.
orl*_*rlp 57
constexpr函数没有副作用,因此可以放心地记忆。鉴于运行时的差异,最简单的解释是编译器在编译时记忆 constexpr 函数。这意味着fibonacci(n)对于 each 只计算一次n,并且所有其他递归调用都从查找表中返回。
为其他人指出的内容添加一些细节:constexpr不必在运行时计算函数,并且可以影响它的参数之一是-fconstexpr-ops-limit.
在 GCC 10.2.0 上,-fconstexpr-ops-limit=1000000000(1B) 并fibonacci(40)生成预编译值,但如果将限制降低到 10000000 (10M),则函数将在运行时计算。如果要确保始终在编译时计算该值,则需要在函数之外标记long long num为。constexprfibonacci
注意:相反的例子是在编译时计算的非 constexpr 函数(优化后),并用 标记它__attribute__ ((const))可能有助于编译器做出这样的决定。但是,我的编译器没有优化它。
| 归档时间: |
|
| 查看次数: |
2610 次 |
| 最近记录: |