从下面的代码sizeof(Base) == 24
和sizeof(Derived) == 24
.
为什么他们的尺寸相同?
在Base
课堂上我们有3名成员,在Derived
课堂上我们有另一名成员.
class Base
{
private:
double d;
protected:
long l;
public:
int i;
};
class Derived : public Base
{
private:
float f;
};
Run Code Online (Sandbox Code Playgroud)
AnT*_*AnT 51
碰巧你的类Base
有8字节对齐要求,但它的最后一个成员大小为4.这导致在Base
内存布局结束时添加了一个空填充区域.当你自己实例化类Base
的对象时,额外的填充扮演它的角色,就像所谓的最派生对象一样.
Base b; // <- a most-derived object
Base a[10]; // <- an array of most-derived objects
Run Code Online (Sandbox Code Playgroud)
但是,当您将"嵌入" Base
作为基类进入类Derived
时,在嵌入的Base
子对象的末尾不需要额外的填充.
Derived d; // <- object `d` contains an embedded sub-object of type `Base`
Run Code Online (Sandbox Code Playgroud)
智能编译器将尝试通过将类的额外字段Derived
放入用于填充的布局区域来重用该区域Base
.在你的情况下,额外的字段Derived::f
偶然具有4字节的相同大小,即它完全适合那里.最终结果是该类的总大小不会增加.
非常相似(实际上)的效果是所谓的"空基优化".在C++中sizeof
,任何类型都保证大于0,这意味着sizeof
空类总是大于零.但是,当您从空基类派生其他类时,您可能会发现基类对派生类的大小贡献了0个字节.例如
struct A {};
struct B {};
struct C {};
struct D {};
struct F : A, B, C, D {
int i;
}
int main() {
std::cout << sizeof(A) << std::endl << sizeof(B) << std::endl <<
sizeof(C) << std::endl << sizeof(D) << std::endl;
std::cout << sizeof(F) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
即使sizeof
每个基类大于零,sizeof(F)
通常仍会评估sizeof(int)
,就好像基类子对象根本不存在一样.
换句话说,正如这样的例子所示,基类子对象关于它们的存储器布局遵循比大多数派生对象明显更宽松的规则.这些宽松的规则可能很容易导致sizeof
基类只sizeof
对派生类产生部分贡献的情况.
因为你有sizeof(double)== sizeof(long)== 8,这通常意味着alignof(double)也等于8.这意味着Base必须在8字节边界上进行大小对齐,以防它存储在数组中,并且它在结尾处生成4字节填充,Derived会删除它以放置f.
使用pahole来弄清楚:
class Base {
private:
double d; /* 0 8 */
protected:
long int l; /* 8 8 */
int i; /* 16 4 */
/* size: 24, cachelines: 1, members: 3 */
/* padding: 4 */
/* last cacheline: 24 bytes */
};
class Derived : public Base {
public:
/* class Base <ancestor>; */ /* 0 24 */
/* XXX last struct has 4 bytes of padding */
private:
/* Bitfield combined with next fields */
float f; /* 20 4 */
/* size: 24, cachelines: 1, members: 2 */
/* paddings: 1, sum paddings: 4 */
/* last cacheline: 24 bytes */
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2504 次 |
最近记录: |