如何判断表达式是在编译时还是运行时计算的?
How to tell if expression is evaluated at compile time or runtime?
我有一个相当大的 Map 对象,我想有一个单独的列表来排序键。这将在我的poject的许多其他源文件中使用。
问题是关于我如何知道何时十一提/定义是编译时作业。如果是这种情况,我应该在哪里查找?我的意思是怎么分辨?
在下面的示例中,源文件中的列表是编译时作业还是在运行时发生?
另外,有没有办法在编译时进行排序操作?
// global.h
extern QMap<int, QString> G_MAP;
extern QList<int> G_MAP_SKEYS_SORTED;
// global.cpp
QMap<int, QString> G_MAP = { /* some hand filled (static) data */ };
QList<int> G_MAP_SKEYS_SORTED = G_MAP.keys();
// main.cpp
int mian() {
// Somewhere I do the sort
std::sort(G_ListRegistersSorted.begin(), G_ListRegistersSorted.end());
}
如果将结果分配给constexpr
变量、在static_assert
或noexcept
语句中使用或用作模板参数,则在编译时计算表达式。这称为 constexpr 上下文。
例如:
// Function which can calculate the fibbonacci sequence at compiletime
constexpr int fib(int n) {
if(n == 0 || n == 1) return n;
return fib(n - 1) + fib(n - 2);
}
int main() {
// This one is calculated at compiletime
constexpr int fib10_at_compiletime = fib(10);
// This one is calculated at runtime
// (unless the compiler was really aggressive when doing optimizations)
int fib10_at_runtime = fib(10);
}
为了在编译时调用函数或其他东西,需要将其标记为constexpr
。
在编译时可以做什么?
C++11:
- 声明变量(但不修改它们)
- 调用其他 constexpr 函数
- 调用 constexpr 构造函数(和默认构造函数)
- 使用阵列和
std::array
- 使用static_asserts和东西
typedef
和using
声明
C++14 新增:
- 您现在也可以使用 lambda
- 您可以在 constexpr 函数中修改变量 您可以使用更改成员
- 变量的 constexpr 成员函数
- 您可以将引用(非常量类型)传递给 constexpr 函数
C++20 新增:(C++20 将于 2020 年推出)
- 您现在可以分配内存
- 您现在可以调用虚拟函数
- 你可以有
try-catch
块
std::sort
是骗子吗?
为了在 constexpr上下文中使用函数,必须将其标记为 constexpr(它附带了一组关于您可以在函数中执行的操作的限制;这些限制将在下面讨论)。在 C++11 中,std::sort
不是 constexpr,因为它打破了这些限制(直到 C++20 它才会成为 constexpr)。
但是,如果允许您使用 C++14,则可以编写自己的排序函数,该函数在编译时工作。
完整概述:https://en.cppreference.com/w/cpp/language/constexpr
另外,有没有办法在编译时进行排序操作?
简短的回答:不。
长答案。
否,因为std::sort()
仅从 C++20 开始constexpr
(您标记为 C++11),因为void
函数 (std::sort()
) 不能在 C++11 中constexpr
,因为QMap
和QList
不是constexpr
类(如果我没记错的话),因为您没有将涉及GMAP
和其他对象声明为constexpr
, 等。
但是,假设有一个MyMap
类定义constexpr
,一个MyList
类声明constexpr
,一个定义constexpr
MySort()
函数,你可以写类似的东西(从C++14开始,因为在C++11中你不能写一个如此复杂的constexpr
函数)
constexpr MyList foo ()
{
MyMap mm { /* some values */ };
MyList ml { ml.keys() };
MySort(ml.begin(), ml.end());
return ml;
}
// ...
constexpr auto ml_final { foo() };
请注意,ml_final
被声明为constexpr
。
如果可能,这需要强制(pre C++20)编译器初始化值编译时,或者如果不可能,则给出编译错误。
- GDB 如何在运行时计算C++表达式
- 如何计算三角数生成的运行时复杂度
- 如何判断表达式是在编译时还是运行时计算的?
- 常量操作是否在运行时计算
- 我的LCS实现的运行时计算
- 为什么我的编译器在 64 位计算机上运行时使用 8 位字符?
- 构建计算机上的C++运行时版本与客户计算机
- 如何在C/C++中从运行时卸载内存偏移量计算
- sizeof 是否在编译时或运行时计算
- 如何在 OpenCL 中运行时获取计算单元 ID
- C++ 运行时计算的常量变量
- 类型id(T) 是在运行时还是在编译时被计算
- 使用非类型可变模板的运行时计算
- 创建一个std::数组,其大小在运行时计算
- 运行时重新计算Qt小部件大小
- 如何在运行时计算数据类型滚转之前允许的最大值
- 初始化值是在编译时计算还是在运行时计算
- 在高度优化的代码中计算代码运行时
- windows运行时-{c++}程序在没有visual Studio的计算机上运行时会发送错误0xc00007b
- 有没有更好的方法可以通过模板用预先计算的值填充数组(用于运行时)