C++ const char*constexpr在编译时和运行时计算
在下面的示例中,我使用C++ const char*constexpr在编译时和运行时计算,c++,c++11,visual-c++,visual-studio-2015,constexpr,C++,C++11,Visual C++,Visual Studio 2015,Constexpr,在下面的示例中,我使用static\u assert验证foo是否在编译时确定。static\u assert通过,我用一个不正确的条件检查它是否实际处于活动状态。这意味着编译时已知foo。但是如果我使用调试器一步一步地检查代码,我会看到skip\u first\u word也会在运行时执行 // Skip the first word in p_str constexpr const char * skip_first_word(const char * p_str) { return
static\u assert
验证foo
是否在编译时确定。static\u assert
通过,我用一个不正确的条件检查它是否实际处于活动状态。这意味着编译时已知foo
。但是如果我使用调试器一步一步地检查代码,我会看到skip\u first\u word
也会在运行时执行
// Skip the first word in p_str
constexpr const char * skip_first_word(const char * p_str) {
return (*p_str == '\0') ? p_str :
(*p_str == ' ') ? p_str + 1 :
skip_first_word(p_str + 1);
}
// constexpr to calculate the length of a string
constexpr size_t str_len(const char * p_str) {
return (*p_str == '\0') ? 0 : str_len(p_str + 1) + 1;
}
int main()
{
constexpr auto foo = skip_first_word("Hello, World!");
constexpr auto foo_size = str_len(foo);
static_assert(foo_size == 6, "Wrong size");
// This assert successfully fails
// static_assert(foo_size == 7, "Wrong size");
// Prevent optimizations
for(auto ptr = foo; *ptr != '\0'; ++ptr) {
volatile auto sink = ptr;
}
volatile auto sink = &foo_size;
return 0;
}
这是怎么回事?为什么不能在运行时使用编译时计算的foo
编辑:在Visual Studio 2015中观察到这种行为显示,您的代码使用-std=c++11-O1
标志,同时使用gcc 7和clang 3.9进行了完全优化
取消对volatile
操作的注释显然会生成汇编指令,但不会为跳过第一个单词或str\u len
生成指令
关于Visual Studio:使用显示正在为以下对象生成程序集,您是正确的:
constexpr auto foo = skip_first_word("Hello, World!");
constexpr auto foo_size = str_len(foo);
这似乎是编译器实现的一个缺陷,因为constepr
变量应该并且可以在编译时完全计算。此外,变量在静态断言
中使用,该断言保证在编译时进行评估。这似乎表明编译器正在不必要地为跳过第一个单词和str_len
生成程序集,即使它们从未在运行时上下文中使用
手动内联代码,如下所示
static_assert(str_len(skip_first_word("Hello, World!")) == 6, "Wrong size");
static_assert(str_len(skip_first_word("Hello, World!")) != 7, "Wrong size");
.您在这两种情况下都使用了相同的优化级别,对吗?@n.caillou是的,我在有优化和没有优化的情况下运行了这两种情况。@FrançoisAndrieux:更新了我的答案以涵盖VS2015行为