什么时候编译器可以静态绑定对虚函数的调用?

Car*_*los 13 c++ compiler-construction polymorphism performance visual-studio-2010

我期望编译器能够静态解析对函数的函数调用,如果类的类型在编译时是已知的(例如,如果没有通过引用或指针使用类实例,如案例1中所示)下面).

但是,我观察到Visual Studio 2010的C++编译器有一种奇怪的行为,我想知道当虚拟类的实例时,编译器是否有任何理由不静态绑定对"正确"虚函数的调用函数是通过引用访问的结构中的成员.

我是否希望编译器在下面的案例2中静态绑定对f()的调用?cr的"参考"是否会以某种方式传播到cr.a,即使它a是一个A而不是一个A&

struct A
{
    virtual void f() ;
    virtual ~A() ;
};

struct B : A
{
    virtual void f() ;
    virtual ~B() ;
};

struct C {
    A a ;
    B b ;
};

C & GetACRef() ;

void test()
{
    // Case 1) The following calls to f() are statically bound i.e.
    // f() is called without looking up the virtual function ptr.
    C c ;  
    c.a.f() ;
    c.b.f() ;
    A a ;
    a.f() ;

    // Case 2) The following calls to f() go through the dynamic dispatching
    // virtual function lookup code. You can check if you generate the .asm
    // for this file.
    C & cr = GetACRef() ; // Note that C is not polymorphic
    cr.a.f() ; // visual C++ 2010 generates call to f using virtual dispatching
    cr.b.f() ; // visual C++ 2010 generates call to f using virtual dispatching  
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*urr 2

我不知道为什么 MSVC 不将您的“案例 2”场景编译为直接调用 - 这当然是可能的。我想只有微软才能回答这个问题。

请注意,GCC 确实会执行您正在寻找的优化(使用 MinGW 4.5.1 和 进行测试-O2)。

此外,MSVC 即使对于以下序列也使用了 vtable 调度(为了清楚起见 - 我正在使用/Ox优化选项):

A a;
A& ar(a);
ar.f();
Run Code Online (Sandbox Code Playgroud)

因此,不需要函数或容器结构向编译器添加潜在的混乱层 - 编译器没有理由不能ar.f()按照该序列进行完全相同的处理a.f()。但正如博·佩尔森(Bo Persson)所建议的那样,也许这不是一个极其常见的优化场景(或者微软只是没有抽出时间来解决它)。同样,只有 MS 的编译器开发人员才能回答。

不过,我不确定是否会将这种行为归类为“奇怪”——这只是一个被错过的优化机会。我不确定这种事情有多常见。在这种情况下,您是否应该期望编译器生成静态绑定调用?或许。但我认为这种情况没有发生也不足为奇。

也许应该在 MS Connect 上提出一个问题。