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

编译器虚拟化,不是太聪明?

如何解决《编译器虚拟化,不是太聪明?》经验,为你挑选了1个好方法。

我写了这个简短的程序,看看虚拟化是如何工作的.编译器应该能够推导出正确的类型:

#include 
using std::cout;
using std::endl;

class Base 
{
public:
    void foo() { cout << "Base::foo" << endl; }
    virtual void bar() { cout << "Base::bar" << endl; }
    virtual ~Base() = default;
};

class Child : public Base 
{
public:
    void foo() { cout << "Child::foo" << endl; }
    void bar() { cout << "Child::bar" << endl; }
};

int main()
{
    Base* obj = new Child;
    obj->foo();
    obj->bar();
    delete obj;
}

-O2 -std=c++11通过https://gcc.godbolt.org/使用gcc 5.3和clang 3.7进行编译.

结果是,两个编译器都无法优化所有内容 - gcc内联foo()并进行虚拟调用,bar()而clang调用foo()和虚拟化以及内联调用bar().

同时,如果我打电话obj->bar();然后obj->foo();,编译器在优化方面没有问题 - clang内联两个调用和gcc正常调用bar()而不是虚拟调用和内联调用foo().

谁能解释这种行为?



1> Jens..:

这可能是因为编译器认为内联没有帮助,因为cout与函数调用的开销相比,它太昂贵了.如果用更简单的东西替换它,例如对成员的分配,它将被内联.请参阅下面的输出

#include 
using std::cout;
using std::endl;

class Base 
{
public:
    void foo() { i = 1; }
    virtual void bar() { i = 2; }
    virtual ~Base() = default;

    int i = 0;
};

class Child : public Base 
{
public:
    void foo() { i = 3; }
    void bar() { i = 4; }
};

int main()
{
    Base* obj = new Child;
    obj->foo();
    obj->bar();
    std::cout << obj->i << std::endl;
    //delete obj;
}

部件:

Base::bar():
        movl    $2, 8(%rdi)
        ret
Child::bar():
        movl    $4, 8(%rdi)
        ret
Base::~Base():
        ret
Child::~Child():
        ret
Child::~Child():
        jmp     operator delete(void*)
Base::~Base():
        jmp     operator delete(void*)
main:
        subq    $8, %rsp
        movl    $16, %edi
        call    operator new(unsigned long)
        movl    $4, %esi
        movl    std::cout, %edi
        call    std::basic_ostream >::operator<<(int)
        movq    %rax, %rdi
        call    std::basic_ostream >& std::endl >(std::basic_ostream >&)
        xorl    %eax, %eax
        addq    $8, %rsp
        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

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