【问题标题】:What will be the size of derived C++ class if base class has no members?如果基类没有成员,派生的 C++ 类的大小是多少?
【发布时间】:2017-10-26 12:51:35
【问题描述】:

考虑以下继承:

class Base {
protected:
  Base() { }
public:
  double Multiply(double x);
};

class Derived : public Base {
  double _value;
public:
  Derived(double init) : _value(init) { }
  double Multiply(double x) { return x*_value; }
};

此代码段将在模板代码库中使用。多态不是一个选项,因为它增加了 VTable 指针,从而使内存消耗加倍。

但是,我怀疑由于 C++ 要求对象的大小至少为 1 字节,Derived 的大小将变为 9 字节,因此,由于填充/对齐,它将进一步变为 16 字节。

那么在 C++ 中有没有办法让 Derived 的大小等于 double 的大小(通常是 8 个字节)? 标准对Derived 的大小有何规定? 特别是,MSVC++ 在这种情况下的表现如何?

【问题讨论】:

  • @AndyG,我不喜欢pack(1),因为虽然我会通过使Derived 9 个字节长来节省内存,但我会因为未对齐访问double 值而受到巨大的惩罚,我将失去有效使用 AVX2 的可能性。
  • 或者,您可以使用 C++11(我忘记了这一点的额头拍打)使用 alignas 强制它
  • 您可以在 MSVC 中检查自己。试试constexpr auto test = sizeof(Derived);。 Intellisense 应该可以为你提供test 的值,你甚至不需要编译。
  • 它可能已经是 8 个字节了 - 但请检查一下 - 这是由于 空基类优化。查一下。

标签: c++ generics inheritance size sizeof


【解决方案1】:

这称为空基优化,标准定义如下:

1.8 C++ 对象模型 [intro.object]

7 除非它是一个位域(9.2.4),一个最衍生的对象应该有一个非零大小并且应该占用一个或多个字节的存储空间。基类子对象的大小可能为零。普通可复制或标准布局类型 (3.9) 的对象应占用连续的存储字节。

8 除非对象是位域或大小为零的基类子对象,否则该对象的地址就是地址 它占用的第一个字节。具有重叠生命周期但不是位域的两个对象 a 和 b 可能具有 如果一个嵌套在另一个中,或者如果至少一个是零大小的基类子对象,并且 它们是不同的类型;否则,它们具有不同的地址。

在您的示例中,继承 Base 类不会影响 Derived 类的大小。但是,MSVC++ 仅对第一个空基类执行此类优化,因此从添加的空基类继承将导致Derived 类大小的增长。我相信长期以来这一直是对 MSVC++ 的批评点,因为许多其他编译器都没有这个问题。如果你有很多小的辅助类,这可能真的很麻烦。作为一种解决方法,可以使用派生模板基类将多继承转换为单继承链:

class Base1
{};

template< typename TBase > class Base2: public TBase
{};

template< typename TBase > class Base3: public TBase
{};

class Derived: public Base3< Base2< Base1 > >
{};

MS Connect bug page。看来他们毕竟没有打算修复它。

【讨论】:

    猜你喜欢
    • 2013-11-25
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多