Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ const char*constexpr在编译时和运行时计算_C++_C++11_Visual C++_Visual Studio 2015_Constexpr - Fatal编程技术网

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 7clang 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行为