对于以下代码片段。
/*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字节的对象),在其他每种情况下,对象大小似乎都是由字节边界决定。
这是什么原因?我问,因为此时我猜。
答案 0 :(得分:6)
我不确定问题是什么,但我会猜测并假设你对sizeof(A)==1
,X
来自{{1}的事实感到困惑添加A
字段,然而char
(虽然您希望它为{1}}的2 - 1,sizeof(X)==1
中的A
这称为“空基类优化”。在C / C ++中,一个对象必须具有非零大小(ISO C ++ 1.8 [intro.object] / 5) - 这间接暗示每个对象都有一个不同的地址,尽管是工会 - 所以即使对于一个空类,它仍然必须至少1个字节。但是,当对象是另一个对象的基类子对象时,此限制将被解除。因此,char
的实例本身必须至少为1个字节,但是当X
是另一个类的基类时,不再需要它,并且编译器可以摆脱那个虚拟完全填充;因此A
的大小仅来自其A
字段。
答案 1 :(得分:3)
这是Stroustrup的explanation,为什么空类的大小不能为零。至于为什么它是1个字节,而不是符合对齐边界的东西,我猜这取决于编译器。