从带有虚函数的基类继承的类上的 sizeof
对于以下代码片段。
/*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 字节的对象),在所有其他情况下,对象大小似乎由字节边界。
这是什么原因呢?我问,因为此时我正在猜测。
For the following code fragment.
/*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;
}
The behaviour I seem to notice is that whenever an empty class is instantiated or an empty class is inherited from byte boundaries are not considered(ie: an object of size 1 byte is allowed), in every other case object size seems to be determined by byte boundaries.
Whats the reason for this? I ask since at this point I am guessing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不确定问题是什么,但我会大胆猜测并假设您对
sizeof(A)==1
,X< /code> 派生自
A
添加一个char
字段,但sizeof(X)==1
(虽然您希望它是2 - 一个用于A
,一个用于X
中的char
)。这称为“空基类优化”。在 C/C++ 中,对象必须具有非零大小 (ISO C++ 1.8[intro.object]/5) - 这间接意味着每个对象都有一个不同的地址,尽管有联合 - 因此即使对于空类,它仍然必须至少为 1 个字节。但是,当一个对象是另一个对象的基类子对象时,此限制将被解除。因此,
A
的实例本身必须至少为 1 个字节,但是当A
是另一个类的基类时,就不再有此要求,并且编译器可以完全摆脱那个虚拟填充;因此X
的大小仅来自其char
字段。I'm not sure what the question is about, but I'll make a wild guess and assume that you're confused by the fact that
sizeof(A)==1
,X
derives fromA
adding achar
field, and yetsizeof(X)==1
(while you'd expect it to be 2 - one forA
, one forchar
inX
).This is known as "empty base class optimization". In C/C++, an object must have a non-zero size (ISO C++ 1.8[intro.object]/5) - this indirectly implies that every object has a distinct address, unions notwithstanding - so even for an empty class, it still has to be at least 1 byte. However, when an object is a base class subobject of another object, this restriction is lifted. Thus, an instance of
A
must be at least 1 byte by itself, but whenA
is a base class of another class, there's no requirement for that anymore, and the compiler can get rid of that dummy padding entirely; so the size ofX
comes only from itschar
field.这是 Stroustrup 对空类大小的解释不能为零。至于为什么它是 1 个字节,而不是符合对齐边界的东西,我猜这取决于编译器。
Here is Stroustrup's explanation of why size of an empty class cannot be zero. As to why it is 1 byte, as opposed to something that conforms to the alignment boundaries, I would guess this depends on the compiler.