"constexpr" 在 C++14 中
"constexpr" in C++14
因此,从 C++14 开始,constexpr
在 C++11 中的限制已经消失,例如 constexpr
函数中有新变量或循环。
并且最新版本的 GCC 和 Clang 编译器已经支持它们。
所以问题是... constexpr
函数是在编译期间计算的,而不是在执行期间计算的,只要作为参数传递给它的值是常量。所以我在下面编写的函数的结果应该在执行期间立即出现,对吗?但事实并非如此。
我的问题是:为什么会这样?我对 C++14 的 constexpr
功能有错误的理解吗?谢谢。
编辑:是的,我使用的是 -OO
,这就是它不起作用的原因。但是设置 -O1
或更高的速度优化就可以了,程序会按预期执行。谢谢大家的回答。
#include <iostream>
#include <chrono>
constexpr long long addition(long long num)
{
long long sum = 0;
for (int i = 0; i <= num; i++)
{
sum += i;
}
return sum;
}
int main()
{
auto start = std::chrono::steady_clock::now();
//////////////////////////////////////////////
std::cout << addition(500000000); //500 mill //executes in 1.957 seconds
///////////////////////////////////////////////
auto stop = std::chrono::steady_clock::now();
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << "\n\nIt took " << static_cast<double>(dur.count()) / 1000 << " seconds!";
std::cin.get();
}
A constexpr function is computed during compile time and not during execution, as long as the value being passed to it as a parameter is a constant.
不,编译器可以自行决定这样做,就像 "pure" 函数不是 constexpr
一样。除非您在需要编译时常量的上下文中使用它,例如 constexpr 变量的初始化,或在数组绑定中使用(但要注意 VLA g++ 扩展)或作为非类型模板参数。对于这些情况,需要编译时评估。 (这不是一个详尽的列表:还有其他上下文需要编译时常量,例如 switch case 标签,但是如何将 case 标签值发送到 cout
?)
为了补充@Ben Voigt 的答案,这里有一个可以立即运行的实际工作示例:
#include <iostream>
#include <chrono>
constexpr long long addition(long long num)
{
long long sum = 0;
for (int i = 0; i <= num; i++)
{
sum += i;
}
return sum;
}
int main()
{
auto start = std::chrono::steady_clock::now();
//////////////////////////////////////////////
constexpr auto res = addition(500000);
std::cout << res; //500 mill //executes in 0 seconds
///////////////////////////////////////////////
auto stop = std::chrono::steady_clock::now();
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << "\n\nIt took " << static_cast<double>(dur.count()) / 1000 << " seconds!";
std::cin.get();
}
Live Example。请注意,我必须从您的输入大小中去掉几个 0。您可以使用 -fconstexpr-steps=N
编译器选项(对于 Clang)进行调整。
因此,从 C++14 开始,constexpr
在 C++11 中的限制已经消失,例如 constexpr
函数中有新变量或循环。
并且最新版本的 GCC 和 Clang 编译器已经支持它们。
所以问题是... constexpr
函数是在编译期间计算的,而不是在执行期间计算的,只要作为参数传递给它的值是常量。所以我在下面编写的函数的结果应该在执行期间立即出现,对吗?但事实并非如此。
我的问题是:为什么会这样?我对 C++14 的 constexpr
功能有错误的理解吗?谢谢。
编辑:是的,我使用的是 -OO
,这就是它不起作用的原因。但是设置 -O1
或更高的速度优化就可以了,程序会按预期执行。谢谢大家的回答。
#include <iostream>
#include <chrono>
constexpr long long addition(long long num)
{
long long sum = 0;
for (int i = 0; i <= num; i++)
{
sum += i;
}
return sum;
}
int main()
{
auto start = std::chrono::steady_clock::now();
//////////////////////////////////////////////
std::cout << addition(500000000); //500 mill //executes in 1.957 seconds
///////////////////////////////////////////////
auto stop = std::chrono::steady_clock::now();
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << "\n\nIt took " << static_cast<double>(dur.count()) / 1000 << " seconds!";
std::cin.get();
}
A constexpr function is computed during compile time and not during execution, as long as the value being passed to it as a parameter is a constant.
不,编译器可以自行决定这样做,就像 "pure" 函数不是 constexpr
一样。除非您在需要编译时常量的上下文中使用它,例如 constexpr 变量的初始化,或在数组绑定中使用(但要注意 VLA g++ 扩展)或作为非类型模板参数。对于这些情况,需要编译时评估。 (这不是一个详尽的列表:还有其他上下文需要编译时常量,例如 switch case 标签,但是如何将 case 标签值发送到 cout
?)
为了补充@Ben Voigt 的答案,这里有一个可以立即运行的实际工作示例:
#include <iostream>
#include <chrono>
constexpr long long addition(long long num)
{
long long sum = 0;
for (int i = 0; i <= num; i++)
{
sum += i;
}
return sum;
}
int main()
{
auto start = std::chrono::steady_clock::now();
//////////////////////////////////////////////
constexpr auto res = addition(500000);
std::cout << res; //500 mill //executes in 0 seconds
///////////////////////////////////////////////
auto stop = std::chrono::steady_clock::now();
auto dur = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
std::cout << "\n\nIt took " << static_cast<double>(dur.count()) / 1000 << " seconds!";
std::cin.get();
}
Live Example。请注意,我必须从您的输入大小中去掉几个 0。您可以使用 -fconstexpr-steps=N
编译器选项(对于 Clang)进行调整。