GCC和反虚拟化内联

GCC and devirtualization inlining

本文关键字:虚拟化 GCC      更新时间:2023-10-16

为什么,在下面的代码中,编译器,知道确切的类型,不能内联虚函数?

https://goo.gl/AgvefX

using namespace std;
struct Base{
    void fire(){
        show();
    }
    virtual void show() =0;/*{
        cout << "base";
    }*/
};
struct A : Base{
    inline __attribute__((__always_inline__)) void show() {
        cout << "a";
    }
};
int main() {
    A a;
  for (int i=0;i<1000;i++){
    a.fire();
  }
    //a.fire();
    return 0;
}

我能在没有CRTP的情况下做些什么吗?

我不擅长阅读汇编代码,但我看到你的例子,当在main:

  1. 1000被加载到寄存器
  2. 1被减去,
  3. a的地址被加载,
  4. 之前调用输出操作符
  5. 跳回循环的开始。

我没有看到呼叫fireshow。它保留了显示的实现,但没有使用它。这是正确的,因为它有外部连杆。

如果您将所有内容放在匿名命名空间中,则可以省略实现。

你能把你对汇编代码的推理放在你的问题中吗?作为参考,下面是从提供链接生成的汇编代码:

.LC0:
    .string "a"
A::show():
    movl    $1, %edx
    movl    $.LC0, %esi
    movl    std::cout, %edi
    jmp std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
main:
    pushq   %rbx
    movl    $1000, %ebx
.L3:
    movl    $1, %edx
    movl    $.LC0, %esi
    movl    std::cout, %edi
    call    std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
    subl    $1, %ebx
    jne .L3
    xorl    %eax, %eax
    popq    %rbx
    ret
    subq    $8, %rsp
    movl    std::__ioinit, %edi
    call    std::ios_base::Init::Init()
    movl    $__dso_handle, %edx
    movl    std::__ioinit, %esi
    movl    std::ios_base::Init::~Init(), %edi
    addq    $8, %rsp
    jmp __cxa_atexit