简体   繁体   English

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

[英]When can the compiler statically bind a call to a virtual function?

I expected the compiler to be able to statically resolve a function call to a virtual function if the type of the class is known at compile time (eg if the class instance is not being used through a reference or a pointer as illustrated in Case 1) below). 我期望编译器能够静态解析对函数的函数调用,如果类的类型在编译时是已知的(例如,如果没有通过引用或指针使用类实例,如案例1中所示)下面)。

However, I have observed a strange behavior with Visual Studio 2010's C++ compiler and I would like to know if there is any reason for the compiler not to statically bind the calls to the "right" virtual function when the instances of the classes with the virtual functions are members in a structure that is being accessed by reference. 但是,我观察到Visual Studio 2010的C ++编译器存在奇怪的行为,我想知道当虚拟类的实例时,编译器是否有任何理由不静态绑定对“正确”虚函数的调用函数是通过引用访问的结构中的成员。

Should I expect the compiler to statically bind the calls to f() in Case 2) below? 我是否希望编译器在下面的案例2中静态绑定对f()的调用? Is the "reference"ness of cr somehow propagating to cr.a even though a is an A and not an A& ? cr的“参考”是否会以某种方式传播到cr.a,即使aA而不是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  
}

Obviously the compiler writers have not bothered to solve this case. 显然,编译器编写者并不打算解决这种情况。 Perhaps it is not common enough in real code to be worth their attention. 也许在实际代码中不值得他们注意。

If GetACRef is defined elsewhere, it is also possible that C is polymorphic there, which could affect the optimizations. 如果在其他地方定义了GetACRef ,那么C也可能是多态的,这可能会影响优化。

Note that a compiler isn't solving every possible case where a small test program is "obvious" to a human. 请注意,编译器并未解决小型测试程序对人类“显而易见”的每种可能情况。 The compilers' focus is cases that happen often in large real programs. 编译器的重点是经常在大型实际程序中发生的情况。

I don't know why MSVC doesn't compile your "Case 2" scenarios to direct calls - it's certainly possible. 我不知道为什么MSVC不会将你的“案例2”场景编译成直接调用 - 这当然是可能的。 I think that only Microsoft would be able to answer. 我认为只有微软才能回答。

Note that GCC does perform the optimization that you're looking for (tested with MinGW 4.5.1 and -O2 ). 请注意,GCC确实执行了您正在寻找的优化(使用MinGW 4.5.1和-O2进行测试)。

Also, MSVC used vtable dispatch even for the following sequence (for clarity - I'm using the /Ox optimization option): 此外,MSVC甚至按以下顺序使用vtable调度(为清楚起见 - 我使用/Ox优化选项):

A a;
A& ar(a);
ar.f();

So there's no need for a function or container struct to add layers of potential confusion to the compiler - there's no reason the compiler can't treat ar.f() exactly the same as af() in that sequence. 因此,不需要函数或容器结构来向编译器添加潜在的混淆层 - 编译器没有理由不能将ar.f()与该序列中的af()完全相同。 But as Bo Persson has suggested, perhaps it's not an extremely common optimization scenario (or MS have just plain not gotten around to it). 但正如Bo Persson所暗示的那样,也许这不是一个非常常见的优化方案(或者MS很明显没有得到它)​​。 Again, only the compiler devs at MS could answer. 同样,只有MS的编译器开发人员才能回答。

I'm not sure I'd classify this behavior as 'strange' though - it's an optimization opportunity that's missed is all. 我不确定我会把这种行为归类为“奇怪” - 这是一个错过的优化机会。 I'm not sure how common this kind of thing might be. 我不确定这种事情有多常见。 Should you expect the compiler to generate statically bound calls in this case? 在这种情况下,您是否希望编译器生成静态绑定调用? Maybe. 也许。 But I think it's not too surprising that it doesn't happen. 但我认为不会发生这种情况并不太令人惊讶。

Maybe an issue should be opened on MS Connect. 也许应该在MS Connect上打开一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM