首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么现代编译器对C++11和更高版本进行了优化?

为什么现代编译器对C++11和更高版本进行了优化?
EN

Stack Overflow用户
提问于 2021-12-28 12:08:27
回答 1查看 93关注 0票数 3

我迷路了。我想利用编译器资源管理器来实验多线程C代码,并从一段简单的代码开始。代码是用-O3编译的。

代码语言:javascript
复制
static int hang = 0;

void set_hang(int x) {
    hang = x;
}

void wait() {
    while (hang != 0) {
        // wait...
    }
}

令我惊讶的是,这是编译器的输出:

代码语言:javascript
复制
set_hang(int):
        mov     dword ptr [rip + hang], edi
        ret
wait():
        ret

我花了一段时间才注意到,我正在以C++而不是C的形式编译代码。切换到C给了我一些我所期望的东西:

代码语言:javascript
复制
set_hang:
        mov     DWORD PTR hang[rip], edi
        ret
wait:
        mov     eax, DWORD PTR hang[rip]
        test    eax, eax
        je      .L3
.L5:
        jmp     .L5
.L3:
        ret

因此,当编译为C++时,wait()总是返回,不管之前传递给set_hang()的是哪个值。我通过编译和我的电脑上的代码来确认这一点。此代码立即存在,而我希望它会提前挂起:

代码语言:javascript
复制
int main(void) {
    set_hang(1);
    wait();
    return 0;
}   

事实上,如果我用gcc而不是g++编译它,它就挂起了。

我用不同的编译器(Clang和GCC)进行了实验,而这种情况只发生在Clang 12.0.0或higer或GCC 10.1或以上。如果我也通过了--std=c++98,我所期望的代码也会发出,所以它似乎是特定于C++11和更高级别的代码。

static中删除hang关键字不会影响发出的程序集。

这里发生了什么事?我写C++已经有几个月了,所以我可能错过了一些关于最新最棒的C++黑魔法的知识,但这是非常简单的代码。我太笨了。

编辑:甚至这个程序也被完全优化了:

代码语言:javascript
复制
// test.cpp
static int hang = 0;

static void set_hang(int x) {
    hang = x;
}

static void wait() {
    while (hang != 0) {
        // wait...
    }
}

int main(void) {
    set_hang(1);
    wait();
    return 0;
}

编译器输出:

代码语言:javascript
复制
main:
        xor     eax, eax
        ret

GCC版10.3.0关于Ubuntu:

此命令将挂起:g++ -O1 -o test test.cpp && ./test

这个命令不会:g++ -O2 -o test test.cpp && ./test

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-12-28 12:48:54

这是因为下面的规则:

intro.progress 该实现可能假定任何线程最终都将执行以下操作之一:

  • 终止,
  • 调用库I/O函数,
  • 通过易失性glvalue执行访问,或
  • 执行同步操作或原子操作。

编译器能够证明一个进入循环的程序永远不会做任何列出的事情,因此它被允许假设循环永远不会被输入。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70506857

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档