3

对于以下代码片段。

/*This program demonstartes how a virtual table pointer 
 * adds to a size of a class*/

class A{

};

class X{
    public:
        void doNothing(){}
    private:
        char a;

};

class Z:public X {

    public:
        void doNothing(){}
    private:
        char z;

}; 

class Y{
    public:
        virtual void doNothing(){}
    private:
        char a;

};

class P:public Y {

    public:
        void doNothing(){}
    private:
        char pp[4];

};

int main(){
    A a;
    X x;
    Y y;
    Z z;
    P p;
    std::cout << "Size of A:" << sizeof(a) << std::endl;// Prints out 1
    std::cout << "Size of X:" << sizeof(x) << std::endl;//Prints out 1
    std::cout << "Size of Y:" << sizeof(y) << std::endl;//Prints 8
    std::cout << "Size of Z:" << sizeof(z) << std::endl;
//Prints 8 or 12 depending upon wether 4 bytes worth of storrage is used by Z data member.
    std::cout << "Size of P:" << sizeof(p) << std::endl;
    std::cout << "Size of int:" << sizeof(int) << std::endl;
    std::cout << "Size of int*:" << sizeof(int*) << std::endl;
    std::cout << "Size of long*:" << sizeof(long*) << std::endl;
    std::cout << "Size of long:" << sizeof(long) << std::endl;
    return 0;

}

我似乎注意到的行为是,每当实例化一个空类或从字节边界继承一个空类时,都不会考虑(即:允许大小为 1 字节的对象),在所有其他情况下,对象大小似乎由字节边界。

这是什么原因?我问,因为在这一点上我猜。

4

2 回答 2

6

我不确定这个问题是关于什么的,但我会做出一个疯狂的猜测并假设您对sizeof(A)==1,X源自A添加一个char字段的事实感到困惑,但是sizeof(X)==1(虽然您希望它是 2 -一个为A,一个为charin X)。

这被称为“空基类优化”。在 C/C++ 中,对象必须具有非零大小(ISO C++ 1.8[intro.object]/5)——这间接意味着每个对象都有一个不同的地址,尽管有联合——所以即使对于一个空类,它仍然必须至少为 1 个字节。然而,当一个对象是另一个对象的基类子对象时,这个限制就被解除了。因此,一个实例A本身必须至少有 1 个字节,但是当A它是另一个类的基类时,就不再需要了,编译器可以完全摆脱那个虚拟填充;所以大小X只来自它的char领域。

于 2009-09-01T19:19:33.770 回答
3

这是 Stroustrup对为什么空类的大小不能为零的解释。至于为什么它是 1 字节,而不是符合对齐边界的东西,我猜这取决于编译器。

于 2009-09-01T19:19:44.113 回答