为什么我添加了一个成员,但sizeof(BaseClass)== sizeof(DerivedClass) [英] Why is sizeof(BaseClass) == sizeof(DerivedClass) although I add a member

查看:63
本文介绍了为什么我添加了一个成员,但sizeof(BaseClass)== sizeof(DerivedClass)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从下面的代码中 sizeof(Base)== 24 sizeof(Derived)== 24 .

为什么它们的大小相等?

Why are their sizes equal?

Base 类中,我们有3个成员,在 Derived 类中,我们有另一个成员.

In Base class we have 3 members and in Derived class we have another member.

class Base
{
private:
    double d;
protected:
    long l;
public:
    int i;
};

class Derived : public Base
{
private:
    float f;
};

推荐答案

碰巧您的类 Base 具有8字节对齐要求,但其最后一个成员的大小为4.在 Base 的内存布局末尾添加了空白填充区域.当您自己实例化 Base 类的对象(即所谓的 most-derived objects )时,这种额外的填充发挥了作用.

It just so happened that your class Base has 8 byte alignment requirement, but its last member has size 4. This leads to an empty padding area added at the end of Base's memory layout. That extra padding plays its role when you instantiate objects of class Base by themselves, as so called most-derived objects.

Base b; // <- a most-derived object
Base a[10]; // <- an array of most-derived objects

但是,当您将 Base 作为基类嵌入"到 Derived 类中时,则不需要在嵌入式 Base 子对象.

However, when you "embed" Base as base class into class Derived, there's no need for that extra padding at the end of the embedded Base subobject.

Derived d; // <- object `d` contains an embedded sub-object of type `Base`

一个聪明的编译器会通过将类 Derived 的额外字段放入用于在 Base 中进行填充的布局区域中来尝试重用该区域.在您的情况下,额外字段 Derived :: f 的大小为4个字节,即恰好适合该字段.最终结果是该班级的总人数没有增加.

A smart compiler will attempt to reuse that area by placing the extra field of class Derived into the layout area used for padding in Base. In your case the extra field Derived::f incidentally has the same size of 4 bytes, i.e. it fits in there perfectly. The end result is that the total size of the class does not increase.

一个非常相似的(本质上)效果被称为空基优化".在C ++中,确保任何类型的 sizeof 都大于0,这意味着空类的 sizeof 始终大于零.但是,当您从一个空的基类派生其他类时,您可能会发现基类为派生类的大小贡献了0个字节.例如

A very similar (in nature) effect is so called "empty base optimization". In C++ sizeof for any type is guaranteed to be greater than 0, which means that sizeof of an empty class is always greater than zero. However, when you derive some other class from an empty base class, you might observe that the base class contributes exactly 0 bytes to the derived class's size. For example

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;
}

即使每个基类的 sizeof 大于零, sizeof(F)通常仍将评估为 sizeof(int),好像根本没有子类.

Even though sizeof of each base class is greater than zero, sizeof(F) will typically still evaluate to sizeof(int), as if base class subobjects do not exist at all.

换句话说,如此类例所示,与大多数派生对象相比,基类子对象在内存布局方面遵循明显更宽松的规则.这些宽松的规则很容易导致基类的 sizeof 仅部分地有助于派生类的 sizeof 的情况.

In other words, as such examples show, base class subobjects follow noticeably more relaxed rules with regard to their memory layout than most-derived objects. These relaxed rules might easily lead to situations when sizeof of base class will only partially contribute to sizeof of derived class.

这篇关于为什么我添加了一个成员,但sizeof(BaseClass)== sizeof(DerivedClass)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆