【问题标题】:Empty derived optimization空派生优化
【发布时间】:2014-03-17 07:01:37
【问题描述】:

大多数 C++ 程序员都知道空基类优化为 technique/idiom空子类会发生什么?例如

class EmptyBase {
    int i;
};

template<typename T>
class Derived : T { 
};

std::cout << sizeof(Derived<EmptyBase>); // Is there a standard verdic on this?

与 EBO 类似,应该有一个 EDO 声明由于派生类不提供任何更多成员,也不向其参数化类型引入任何虚拟成员,它不应该需要更多内存。考虑到可能出现类似情况的各种情况(多继承、单继承……):

  • 这样的优化标准/可能吗?
  • 如果是,这种优化的机制是什么,它们是否类似于EBO's

注意:使用派生自其参数化类型的类模板是相当典型的。主题是关于这种情况下的空间浪费

【问题讨论】:

  • 顺便说一句,“EBO”用词不当。我将其称为“基类布局优化”左右,因为它也可以不平凡地应用于非空类。
  • 另见this question

标签: c++ class optimization memory-management compiler-optimization


【解决方案1】:

标准本身不包含“空基类”案例。相反,它说(参见 1.8):

[A] 大多数派生对象应具有非零大小并应占用一个或多个 字节的存储空间。基类子对象的大小可能为零。

还有:

除非对象是 [...] 大小为零的基类子对象,否则该对象的地址就是它占用的第一个字节的地址。如果一个对象是另一个对象的子对象,或者如果至少一个是零大小的基类子对象并且它们属于不同类型,则两个对象 [...] 可能具有相同的地址;否则,它们将具有不同的地址。

并且(第 9 条):

类类型的完整对象和成员子对象应具有非零大小。脚注:基类子对象没有那么受限。

这绝不是说只有空基地才能适应任何类型的布局更改,并为“挤压”布局留出足够的空间:例如:

struct A {}; struct B : A { int x; };             // "equivalent" to { int }

struct X { int a; }; struct Y : X {};             // "equivalent" to { int }

考虑B b;Y y;。有可能b的地址、bA子对象的地址(即&amp;static_cast&lt;A&amp;&gt;(b))和b.x的地址相同,同样y的地址, X-y的子对象,和y.a的地址是一样的。

唯一不起作用的是:

struct S {}; struct T { S s; };                   // "equivalent" to { char }

"equivalent" 我的意思是最明智、最节省空间的实现。

一个更有趣的案例如下:

struct Foo { int x; char a; };                    // { int, char, char[3] }

struct Bar : Foo { short q; };                    // { int, char, char, short }

此示例假定sizeof(int) == 4sizeof(short) == 2。出于对齐原因,我们有 sizeof(Foo) == 8,但 sizeof(Bar) 也是 8,尽管有更多的数据成员。


该标准的另一个相关部分是 9.2/13:

分配具有相同访问控制(第 11 条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址。未指定具有不同访问控制的非静态数据成员的分配顺序 (11)。实现对齐要求可能会导致两个相邻的成员不能立即分配;管理虚拟功能 (10.3) 和虚拟基类 (10.1) 的空间要求也是如此。

最后,9.2/10 说标准布局类在开头没有填充,因此它们的地址等于它们的“初始成员”的地址。由于标准布局要求所有基都为空,或者派生最多的类本身没有数据成员,这意味着标准布局类必须采用一种“空基”优化,而我上面的BY布局的初始部分其实是强制的。

【讨论】:

猜你喜欢
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 2012-02-13
相关资源
最近更新 更多