GCC和虚拟化内联

时间:2015-09-25 19:32:57

标签: c++ gcc

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

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,我可以做些什么吗?

1 个答案:

答案 0 :(得分:4)

我不擅长阅读汇编程序代码,但是我看到你的例子的方式,在main时:

  1. 1000加载到寄存器
  2. 减去
  3. 1,
  4. &#34; a&#34;的地址已加载
  5. 之前调用输出运算符
  6. 跳回到循环的开头。
  7. 我没有看到对fireshow的来电。它保持show的实现,但它没有被使用。这是正确的,因为它有外部联系。

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

    你可以在你的问题中使用汇编程序代码进行推理吗?作为参考,这里是来自提供链接的生成的汇编代码:

    .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
    
相关问题