在旧测试代码gcc-4.4.0和gcc-4.6.4,编译器能够应用智能优化和预计算的结果const输入:
#include <iostream>
#include <chrono>
using namespace std;
const auto N = 1000000000ULL; // constexptr is tested, no effect
unsigned long long s(unsigned long long n)
{
auto s = 0ULL;
for (auto i = 0ULL; i < n; i++)
s += i;
return s;
}
int main()
{
auto t1 = std::chrono::high_resolution_clock::now();
auto x = s(N);
auto t2 = std::chrono::high_resolution_clock::now();
auto t = std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
cout << "Result: " << x << " -- time (ms):" << t/0.1e7 << endl;
}
Run Code Online (Sandbox Code Playgroud)
N是一个常量值,然后编译器可以s在编译时运行函数并将结果赋值给x.(不需要运行时计算N)
结果在不同版本的gcc(以及一个版本的clang):
0.001532 ms.0.013517 ms.0.001 ms.1313.78 ms!!.题:
注意(1):我测试了两个-O2并-O3切换,没有效果.
注意(2):强制,我指的是编译器的命令和开关.
注(3):函数s只是一个例子,可以用更复杂的函数代替.
您可以使用新的C++ 11 constexpr关键字强制它在编译时运行.
首先,您必须将迭代转换为递归(此要求在C++ 1y中删除),例如:
constexpr unsigned long long s(unsigned long long n)
{
return n? n + s(n-1): 0;
}
Run Code Online (Sandbox Code Playgroud)
或者使用尾递归(当输入变量时,仍适用于运行时计算):
constexpr unsigned long long s_impl( unsigned long long accum, unsigned long long n, unsigned long long n_max )
{
return (n < n_max)? s_impl(accum + n + 1, n + 1, n_max): accum;
}
constexpr unsigned long long s(unsigned long long n)
{
return s_impl(0, 0, n);
}
Run Code Online (Sandbox Code Playgroud)
(在C++ 1y中,您需要做的就是将constexpr关键字添加到现有实现中)
然后用它调用它
constexpr auto x = s(N);
Run Code Online (Sandbox Code Playgroud)