2011-01-23 156 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!

一个空类的大小不能是零,因为在这种情况下相同类别的两个对象将具有,这是不可能的同一地址。

类似地,两个不同对象的两个子对象不能具有相同的地址。你的编译器不符合规范。更改!