【问题标题】:constexpr keywork doesn't affect on code generationconstexpr 键不影响代码生成
【发布时间】:2017-02-22 11:33:26
【问题描述】:

我写了一个简单的程序:

constexpr int strlen_c(char const* s)
{
    return *s ? 1 + strlen_c(s + 1) : 0;
}

int main()
{
    return strlen_c("hello world");
}

我预计编译器会优化函数并在编译时评估其结果。但实际上生成的机器码会循环评估结果:

    mov     edx, offset aHelloWorld ; "hello world"
loc_408D00:
    add     edx, 1
    mov     eax, edx
    sub     eax, offset aHelloWorld ; "hello world"
    cmp     byte ptr [edx], 0
    jnz     short loc_408D00
    leave
    retn

该程序正在使用带有标志-std=c++11 -Ofast -O2 的 g++ 5.3 版编译。我在 Visual Studio 2013 和 g++ 4.9 中获得的结果相同。

疑问编译器无法优化给定代码的原因是什么?

【问题讨论】:

  • g++ 和 clang++ 都优化了代码。这取决于编译器的实现。
  • @VittorioRomeo 你能说一下 g++ 的版本和必要的编译标志吗?
  • GCC 6、ICC 16 和 Clang 3.1 都简单地加载值 11 并返回。这些可以在交互式反汇编站点gcc.godbolt.org 上找到。还有 Microsoft C++ 19.10(我不知道是哪个 Visual Studio),即使 Dinesh 的回答也无法优化。

标签: c++11 g++ compiler-optimization


【解决方案1】:

constexpr 函数不一定总是在编译时求值。但是,如果在 constexpr 上下文中使用,则必须在编译时对其进行评估,因此,无论编译器优化如何,以下内容都将起作用:

int main()
{
   constexpr auto len = strlen_c("hello world");
   return len;
}

以下是为上述代码生成的程序集:

main:
        mov     eax, 11
        ret

Demo

【讨论】:

  • 微软的编译器 still executes strlen_c 在运行时。然后它丢弃结果并返回常量 11。标准不保证性能……
猜你喜欢
  • 2019-07-26
  • 2014-12-30
  • 1970-01-01
  • 2020-09-08
  • 2016-07-09
  • 2015-03-12
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多