当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《constchar*constexpr在编译时和运行时进行评估》经验,为你挑选了1个好方法。

在以下示例中,我用于static_assert验证是否foo在编译时确定.该static_assert通行证和我有一个不正确的条件下,它实际上是积极的检查.这意味着foo在编译时已知.但是,如果我使用调试器逐步执行代码,我会看到它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在运行时使用在编译时计算的那个?

编辑:使用Visual Studio 2015观察到此行为



1> Vittorio Rom..:

gcc.godbolt.org显示您的代码使用标志完全使用gcc 7clang 3.9进行了优化-std=c++11 -O1.

取消注释volatile操作显然会生成汇编指令,但不会为skip_first_word或生成指令str_len.


关于Visual Studio你是正确的:在gcc.beta.godbolt.org上使用CL 19表明正在为以下内容生成程序集:

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

这看起来像编译器实现缺陷,因为constexpr变量应该并且可以在编译时完全计算.另外,变量在a中使用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");

......没有产生额外的装配.

推荐阅读
无名有名我无名_593
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有