簡體   English   中英

什么時候編譯器可以靜態綁定對虛函數的調用?

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

我期望編譯器能夠靜態解析對函數的函數調用,如果類的類型在編譯時是已知的(例如,如果沒有通過引用或指針使用類實例,如案例1中所示)下面)。

但是,我觀察到Visual Studio 2010的C ++編譯器存在奇怪的行為,我想知道當虛擬類的實例時,編譯器是否有任何理由不靜態綁定對“正確”虛函數的調用函數是通過引用訪問的結構中的成員。

我是否希望編譯器在下面的案例2中靜態綁定對f()的調用? 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  
}

顯然,編譯器編寫者並不打算解決這種情況。 也許在實際代碼中不值得他們注意。

如果在其他地方定義了GetACRef ,那么C也可能是多態的,這可能會影響優化。

請注意,編譯器並未解決小型測試程序對人類“顯而易見”的每種可能情況。 編譯器的重點是經常在大型實際程序中發生的情況。

我不知道為什么MSVC不會將你的“案例2”場景編譯成直接調用 - 這當然是可能的。 我認為只有微軟才能回答。

請注意,GCC確實執行了您正在尋找的優化(使用MinGW 4.5.1和-O2進行測試)。

此外,MSVC甚至按以下順序使用vtable調度(為清楚起見 - 我使用/Ox優化選項):

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

因此,不需要函數或容器結構來向編譯器添加潛在的混淆層 - 編譯器沒有理由不能將ar.f()與該序列中的af()完全相同。 但正如Bo Persson所暗示的那樣,也許這不是一個非常常見的優化方案(或者MS很明顯沒有得到它)​​。 同樣,只有MS的編譯器開發人員才能回答。

我不確定我會把這種行為歸類為“奇怪” - 這是一個錯過的優化機會。 我不確定這種事情有多常見。 在這種情況下,您是否希望編譯器生成靜態綁定調用? 也許。 但我認為不會發生這種情況並不太令人驚訝。

也許應該在MS Connect上打開一個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM