2011-01-23 36 views
5

下面是一個關於ebco的簡單測試,我在vc9和g ++上編譯了它。兩個編譯器的輸出都不相同。我想知道的是,vc的行爲是否一致。空基類優化

#include <iostream> 

class empty 
{ 
}; 

class empty_one : public empty {}; 
class empty_two : public empty {}; 

class non_empty 
    : public empty_one 
    , public empty_two 
{ 
}; 

int main() 
{ 
    std::cout << "sizeof(empty): " << sizeof(empty) << std::endl; 
    std::cout << "sizeof(empty_one): " << sizeof(empty_one) << std::endl; 
    std::cout << "sizeof(empty_two): " << sizeof(empty_two) << std::endl; 
    std::cout << "sizeof(non_empty): " << sizeof(non_empty) << std::endl; 

    std::cout << std::endl; 

    non_empty a[2]; 

    void* pe10 = static_cast<empty*>(static_cast<empty_one*>(&a[0])); 
    void* pe20 = static_cast<empty*>(static_cast<empty_two*>(&a[0])); 
    std::cout << "address of non_empty[0]: " << &a[0] << std::endl; 
    std::cout << "address of empty of empty_one: " << pe10 << std::endl; 
    std::cout << "address of empty of empty_two: " << pe20 << std::endl; 

    std::cout << std::endl; 

    void* pe11 = static_cast<empty*>(static_cast<empty_one*>(&a[1])); 
    void* pe21 = static_cast<empty*>(static_cast<empty_two*>(&a[1])); 
    std::cout << "address of non_empty[1]: " << &a[1] << std::endl; 
    std::cout << "address of empty of empty_one: " << pe11 << std::endl; 
    std::cout << "address of empty of empty_two: " << pe21 << std::endl; 
} 

在VC,

pe20 == pe11. (test1) 

兩個對象的兩個子對象可以有相同的地址?這是否符合?

此外,

pe20 >= &a[0] + sizeof(a[0]) (test2) 

可以在子對象的地址傳遞一個對象的結束?

在g ++上,上面的兩個測試不成立。

EDIT:C++ 0x中標準草案,1.8/6,

除非對象是一個位字段或大小爲零的基類子對象,該對象的地址是它佔據的第一個字節的地址。既不是位字段也不大小爲零的基類的子對象兩個不同的對象應具有不同的地址

該標準要求兩個對象具有不同的地址時,它們既不位字段也不基零大小的類子對象。但它不要求兩個零大小的子對象不能有相同的地址。那麼test1可以是真的嗎?

+0

我認爲你可以安全地把它帶到MSVC團隊(除非它已經存在)。 – 2011-01-23 13:23:35

回答

1

pe10 == pe11。兩個對象可以有兩個子對象 具有相同的地址嗎? 這符合?

不,兩個不同的對象不能有相同的地址。如果他們已經,編譯器不是標準投訴。

順便說一下,您正在使用哪種版本的VC++?我使用的是MSVC++ 2008,它的輸出是這樣的:

alt text

我想,你的意思是pe20==pe11?如果是這樣,那麼這也是錯誤的,非標準的。 MSVC++ 2008編譯器有bug!

GCC是正確的;看到輸出自己:http://www.ideone.com/Cf2Ov


類似的話題:

When do programmers use Empty Base Optimization (EBO)

+2

這似乎很破,因爲`pe20`和`pe11`似乎有相同的地址.... – 2011-01-23 04:25:29

+1

我剛剛在我的文章中犯了一個錯誤,其中pe10在兩次測試中應該是pe20。 WRT你的輸出,現在pe20 == pe11,這不應該發生,對吧? – ashen 2011-01-23 04:27:42

1

PE10 PE11 ==。兩個對象的兩個子對象可以具有相同的地址嗎?這是否符合?

Nopes!

一個空類的大小不能是零,因爲在這種情況下相同類別的兩個對象將具有,這是不可能的同一地址。

類似地,兩個不同對象的兩個子對象不能具有相同的地址。你的編譯器不符合規範。更改!