【发布时间】:2016-08-30 06:18:30
【问题描述】:
最近我尝试在 MSVC 2015 下利用 C++0x constexpr,我的目标是实现编译时哈希字符串。我编写了一个简单的 FNV-1a 哈希算法作为 constexpr 函数,根据需要使用单个返回语句(三元运算符)并仅调用 constexpr 函数,这里是:
template <size_t N>
constexpr U32 StringID_FNV1a_32(const char(&str)[N], I32 charIndex = 0, U32 hash = 2166136261U)
{
return charIndex < N-1 ? StringID_FNV1a_32(str, charIndex +1, (hash ^ str[charIndex]) * 16777619U) : hash;
}
我还制作了一个小宏,以便能够轻松更改引擎盖下的算法:
#define STRING_ID(str) core::utility::StringID_FNV1a_32(str)
然后我在我的代码中使用了这个宏,仔细检查是否命中了任何断点以及生成的汇编代码。这是一个小场景:
//1. normal variable test
U32 hash1 = STRING_ID("abc");
//2. enum test
enum {
hash2 = STRING_ID("abc")
};
//3. constexpr variable test
constexpr U32 hash3 = STRING_ID("abc");
这里是事实:
- 在运行时调用了第一个测试
- 在编译时执行了第二次测试
- 在运行时调用了第三个测试
你可以想象我对第一次和第三次尝试有点困惑。
为什么在第三种情况下允许编译器在运行时调用函数?尽管 msdn 明确说明 “const 和 constexpr 变量之间的主要区别在于 const 变量的初始化可以推迟到运行时进行,而 constexpr 变量必须在编译时进行初始化。” [@ 987654321@
可能与我处于调试模式并关闭所有优化的事实有关吗?那么第一次测试呢?有没有办法强制编译器在编译时执行哈希?
【问题讨论】:
-
如果你将 "abc" 设为
constexpr string然后将其传递给函数会发生什么? -
如果你在 constexpr 上下文中使用 hash3,比如
static_assert(hash3 == hash2, "!");,你会看到正确的值在编译时已经可用。然而由于某种原因,它还在运行时再次计算和初始化,这可能是一个错误。 -
@melak47 你对 static_assert 测试的看法是对的......很奇怪......也许这真的是一个错误......
-
@johnbakers 使用 constexpr char str[4] 作为参数不会改变运行时间
标签: c++11 visual-c++ hash constexpr compile-time