const char * constexpr在编译时和运行时进行评估

时间:2017-01-11 15:28:05

标签: c++ c++11 visual-c++ visual-studio-2015 constexpr

在以下示例中,我使用foo来验证在编译时确定static_assertfoo通过,我检查的条件不正确,它实际上是活动的。这意味着skip_first_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

这里发生了什么?为什么在编译时计算的myAPIService.postUploadImage = function (formdata) { var request = { url: urlBase + 'UploadImage', method: 'POST', data: formdata, headers: { 'Content-Type': undefined } } return $http(request); }; 不能在运行时使用?

编辑:Visual Studio 2015中会出现此行为

1 个答案:

答案 0 :(得分:5)

gcc.godbolt.org使用-std=c++11 -O1标记显示您的代码已使用 gcc 7 clang 3.9 完全优化。

取消注释volatile操作显然会生成汇编指令,但不会为skip_first_wordstr_len生成任何说明。

您对Visual Studio的判断是正确的:使用CL 19 on gcc.beta.godbolt.org显示正在为以下内容生成程序集:

constexpr auto foo = skip_first_word("Hello, World!");
constexpr auto foo_size = str_len(foo);

这看起来像编译器实现缺陷,因为constexpr变量应该并且可以在编译时完全计算。此外,变量正在static_assert中使用,保证在编译时评估。这似乎表明编译器不必要地为skip_first_wordstr_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");

...produces no extra assembly