【问题标题】:Size of base class inside derived class派生类中基类的大小
【发布时间】:2017-01-16 09:31:23
【问题描述】:

假设我的课程没有数据:

struct Empty {
  /*some methods here*/
};

还有一个派生类

struct Derived: Empty {
  int a;
  int b;
  char c;
  ....
}__attribute__((packed));`

Empty 类的对象大小 = 1。派生类的空部分通常大小为 0。据我了解,编译器看到基本 Empty 类没有数据,因此它可以优化 Empty 的大小,以防它是“内部”派生的,但标准不需要这样做。

所以问题是:

我能否在编译时以某种方式确定 Derived 类的 Empty 部分并没有真正占用内存。

我知道我可以像sizeof(Derived) = sizeof(a) + sizeof(b) ... 那样进行检查,但它太冗长了,并且有几个类,如 Derived。有没有更优雅的解决方案?

【问题讨论】:

  • 你为什么想知道这个?请注意,成员或基类可以占用内存而不会增加派生类的占用空间(通过使用填充丢失的空间)。另请注意,结构上的sizeof 可以小于或大于其成员和基数的sizeof 之和。
  • 我将使用这些派生类来表示一些网络数据。因此,所有此类派生类都将具有打包属性。此外,我将从一些模板类继承来实现奇怪重复的模板模式。这样所有的派生类都会有一些共同的功能。但是我不希望这种继承影响派生类的布局。

标签: c++


【解决方案1】:

您可以使用std::is_empty 确保您继承的类是零大小的:

static_assert(std::is_empty<Empty>{});

如果是,empty base optimization 就是guaranteed to take place for standard-layout classes


我知道我可以像sizeof(Derived) = sizeof(a) + sizeof(b) ... 这样进行检查,但这太冗长了。有没有更优雅的解决方案?

这不能正常工作,因为您需要考虑填充和最终属性,例如packed

【讨论】:

  • 谢谢。不知道这种优化是有保证的。
  • 标准不保证这种优化。尽管在现实世界的编译器中,这在实践中很常见。
  • @彼得:it is guaranteed for standard-layout classes。我会澄清我的答案。
【解决方案2】:

您可以使用更多“旧”(before C++11)宏 - offsetof:

struct Empty {};
struct NonEmpty {
  int a;
};
struct Derived1: Empty {
  int a;
  int b;
  char c;
};
struct Derived2: NonEmpty {
  int a;
  int b;
  char c;
};
static_assert(offsetof(Derived1,a) == 0,"");
static_assert(offsetof(Derived2,a) != 0,"");

你也可以使用这个宏来检查你的成员变量的顺序:

static_assert(offsetof(Derived,a) < offsetof(Derived,b),"");
static_assert(offsetof(Derived,b) < offsetof(Derived,c),"");

但别忘了——offsetof也有同样的限制:

如果 type 不是标准布局类型,则行为未定义。 如果 member 是静态成员或成员函数,则行为未定义。

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    • 2017-07-06
    相关资源
    最近更新 更多