空基类优化

时间:2011-01-23 03:57:13

标签: c++ g++ visual-c++

以下是对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 ++上,上述两项测试不成立。

编辑:在c ++ 0x标准草案中,1.8 / 6,

  

除非对象是零字段或零大小的基类子对象,否则该对象的地址是它占用的第一个字节的地址。两个不同的对象既不是位字段也不是零大小的基类子对象应具有不同的地址

标准要求当两个对象既不是位字段也不是零大小的基类子对象时,它们具有不同的地址。但它不要求零大小的两个子对象不能具有相同的地址。那么 test1 可以是真的吗?

2 个答案:

答案 0 :(得分:1)

  

pe10 == pe11。可以两个子对象   两个对象有相同的地址?是   这符合吗?

不,两个不同的对象不能有相同的地址。如果他们这样做,编译器就不是标准投诉。

顺便问一下,你正在使用哪个版本的VC ++?我正在使用MSVC ++ 2008,它的输出是:

alt text

我想,你的意思是pe20==pe11?如果是这样,那么这也是错误的,非标准的。 MSVC ++ 2008编译器有bug!

海湾合作委员会是正确的;自己看一下输出:http://www.ideone.com/Cf2Ov


类似主题:

When do programmers use Empty Base Optimization (EBO)

答案 1 :(得分:1)

  

pe10 == pe11。两个对象的两个子对象可以具有相同的地址吗?这符合吗?

Nopes!

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

类似地,两个不同对象的两个子对象不能具有相同的地址。您的编译器不符合要求。改变它!