使用不同参数评估constexpr函数时的运行时差异问题
咱们先拆解一下你的问题,核心是对constexpr的理解偏差,再加上未完成的计时代码,才导致了不同的运行时结果。下面一步步给你解释:
1. 先明确你的函数实际做了什么
你的plusOne函数看起来是递归,但本质是计算从1到输入值i的累加和(当i>0时),等价于数学公式 i*(i+1)/2。比如plusOne(5)就是5+4+3+2+1=15,plusOne(0)返回0。
2. constexpr是“允许编译期计算”,不是“强制编译期计算”
这是很多开发者容易踩的坑:
- 当你用编译期常量调用它时(比如
plusOne(10),这里的10是字面量,编译器在编译阶段就知道它的值),编译器会直接算出结果,运行时根本不会执行递归逻辑,直接用这个预计算好的常量值,耗时几乎为0。 - 但如果你用运行期才能确定的变量调用它(比如
int num = 20; plusOne(num)),编译器没办法提前计算,只能生成递归的机器码,运行时会实际执行递归调用,这时候就会有函数调用的开销,耗时会明显变长。
3. 你的计时代码有明显问题
从你给出的代码片段看,计时的start和finish之间没有包裹任何函数调用,相当于只计时了一段空操作,这样的结果肯定是不准确的。正确的计时写法应该是把要测试的函数调用放在计时区间内,比如:
#include <chrono> #include <iostream> constexpr int plusOne(int i) { return (i > 0) ? i + plusOne(i - 1) : 0; } int main() { // 测试编译期常量调用 auto start = std::chrono::high_resolution_clock::now(); int result_compile = plusOne(100); // 编译期直接算出结果 auto finish = std::chrono::high_resolution_clock::now(); std::cout << "编译期计算耗时: " << std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() << " 纳秒\n"; // 测试运行期变量调用 int runtime_num = 100; start = std::chrono::high_resolution_clock::now(); int result_runtime = plusOne(runtime_num); // 运行时执行递归 finish = std::chrono::high_resolution_clock::now(); std::cout << "运行期计算耗时: " << std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() << " 纳秒\n"; return 0; }
运行这段代码,你会看到第一次计时的结果几乎是0,第二次会有明显的耗时(哪怕数值不大,因为100的递归深度不算特别深)。
4. 额外优化建议:替换递归为公式
递归的constexpr函数虽然合法,但对于这种简单的求和场景,直接用数学公式效率更高,还能避免递归深度限制(比如当i很大时,递归可能会导致栈溢出):
constexpr int plusOne(int i) { return i > 0 ? i * (i + 1) / 2 : 0; }
这个版本不管是编译期还是运行期计算,效率都远超递归版本。
内容的提问来源于stack exchange,提问作者ibezito
相关产品推荐
相关产品推荐

