c++ - C++ 编译器如何如此快速地评估递归 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;
}
如果我从函数中删除constexpr
标识符,则需要很长时间来评估(超过 5 分钟)。但是,当我保持原样时,程序仍会在 3 秒内编译并在不到几毫秒的时间内打印出正确的结果。fibonacci()
fibonacci(70)
0.1
我了解到constexpr
函数是在编译时评估的,所以这意味着fibonacci(70)
编译器会在不到 3 秒的时间内计算出来!但是,C++ 编译器比 C++ 代码具有更好的计算性能似乎不太正确。
我的问题是,C++ 编译器是否真的在我按下“构建”按钮和编译完成之间评估函数?还是我误解了关键字constexpr
?
编辑:这个程序是用g++ 7.5.0
with编译的--std=c++17
。
解决方案
constexpr
函数没有副作用,因此可以放心地记忆。鉴于运行时的差异,最简单的解释是编译器在编译时记忆 constexpr 函数。这意味着fibonacci(n)
每个 只计算一次n
,所有其他递归调用都从查找表返回。
推荐阅读
- testing - 以像素为单位比较实现的网站与其设计的测试工具
- strong-parameters - Rails 5 Api模型不保存字段
- ubuntu - 内核编译错误?
- html - wkhtmltopdf 无法在 Ubuntu 中打印 unicode 字符
- java - 除了默认配置文件外,Maven 配置文件未激活
- python - 如何可视化两个分布
- ios - 在 UICollectionView 中,单元格顺序以及滚动通过 collectionview 后出现在其中的文本字段值是混乱的
- spring-boot - @ApiResponse swagger springfox - 自定义响应容器的使用
- java - Java:备用键盘支持
- java - 即使在覆盖 equals 和 hashCode 方法之后,Java LinkedHashSet 也不会删除重复项