【发布时间】:2020-10-08 23:43:31
【问题描述】:
static 变量不允许在 constexpr 函数中使用。这是有道理的,因为static 会给一个应该是纯函数的状态引入一个状态。
但是,我不明白为什么我们不能在 constexpr 函数中包含 static constexpr 变量。它保证始终具有相同的值,因此该函数将保持纯净。
我为什么要关心?因为static 在运行时会有所不同。考虑这段代码:
#include <array>
constexpr int at(const std::array<int, 100>& v, int index)
{
return v[index];
}
int foo1(int i) {
static constexpr std::array<int, 100> v = {
5, 7, 0, 0, 5 // The rest are zero
};
return at(v, i);
}
constexpr int foo2(int i) {
constexpr std::array<int, 100> v = {
5, 7, 0, 0, 5 // The rest are zero
};
return at(v, i);
}
int foo2_caller(int i) {
return foo2(i);
}
直播:https://gcc.godbolt.org/z/umdXgv
foo1 有 3 个 asm 指令,因为它将缓冲区存储在静态存储中。而foo2 有 15 条 asm 指令,因为它需要在每次调用时分配和初始化缓冲区,而编译器无法对此进行优化。
注意foo1 在这里只是为了显示foo2 中的缺陷。我想编写一个可以在编译和运行时使用的函数。这就是foo2 背后的想法。但我们发现它的效率不如仅运行时的foo1,这令人不安。
我找到的唯一有意义的相关讨论is this,但并没有专门讨论static constexpr。
问题是:
- 我的推理是否正确,还是我错过了
static constexpr变量可能导致的一些问题? - 有解决此问题的建议吗?
【问题讨论】:
-
如果您关心运行时性能,为什么不使用
foo1? -
foo1在这里只是为了显示foo2中的缺陷,我希望它在编译和运行时都可用。 -
@Mikhail 在编译时不会有任何程序集。编译器会将函数调用替换为常量值。
-
@NathanOliver 这就是为什么问题是关于运行时的。我想为两者写一个函数,这就是
foo2的目的。 -
@NateEldredge 我相信
foo1仍然不允许在constexpr上下文中使用。