Nik*_*iou 5 c++ optimization memory-management class compiler-optimization
大多数C++程序员都知道空基类优化作为一种技术/习惯用法.空子课程会发生什么?例如
class EmptyBase {
int i;
};
template<typename T>
class Derived : T {
};
std::cout << sizeof(Derived<EmptyBase>); // Is there a standard verdic on this?
Run Code Online (Sandbox Code Playgroud)
与EBO类似,应该有一个EDO声明由于派生类不提供任何更多成员,也没有将任何虚拟成员引入其参数化类型,因此它不需要更多内存.考虑到类似的东西可能会出现的各种情况(多重继承,单继承...):
注意:使用从其参数化类型派生的类模板是非常典型的.主题是关于在这种情况下的空间浪费
该标准本身不包含"空基类"案例.相反,它说(参见1.8):
[A]大多数派生对象应具有非零大小,并且应占用一个或多个存储字节.基类子对象可以具有零大小.
和:
除非一个对象是零大小的基类子对象,否则该对象的地址是它占用的第一个字节的地址.如果一个是另一个的子对象,或者如果至少有一个是零大小的基类子对象并且它们是不同类型的,则两个对象可以具有相同的地址; 否则,他们应有不同的地址.
并且(第9条):
类类型的完整对象和成员子对象应具有非零大小.脚注:基类子对象不受限制.
这从未说过只有空座可以适应任何类型的布局变化,并留下足够的空间来"挤压"布局:例如:
struct A {}; struct B : A { int x; }; // "equivalent" to { int }
struct X { int a; }; struct Y : X {}; // "equivalent" to { int }
Run Code Online (Sandbox Code Playgroud)
考虑B b;
和Y y;
.它是可能的的地址b
,该的A
的-subobject b
(即&static_cast<A&>(b)
),并且的b.x
是相同的,并且类似地那的地址y
,所述X
的-suboject y
,和地址y.a
是相同的.
唯一不起作用的是:
struct S {}; struct T { S s; }; // "equivalent" to { char }
Run Code Online (Sandbox Code Playgroud)
通过"equivalent"
我的意思是最明智的,节省空间的实现.
一个更有趣的案例如下:
struct Foo { int x; char a; }; // { int, char, char[3] }
struct Bar : Foo { short q; }; // { int, char, char, short }
Run Code Online (Sandbox Code Playgroud)
这个例子假设sizeof(int) == 4
和sizeof(short) == 2
.我们有sizeof(Foo) == 8
对位的原因,但sizeof(Bar)
也8
尽管有多个数据成员.
该标准的另一个相关部分是9.2/13:
分配具有相同访问控制(第11条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.未指定具有不同访问控制的非静态数据成员的分配顺序(11).实施对齐要求可能导致两个相邻成员不能立即分配; 因此,可能需要空间来管理虚拟功能(10.3)和虚拟基类(10.1).
最后,9.2/10表示标准布局类在开头没有填充,因此它们的地址等于其"初始成员"的地址.由于标准布局要求所有基都为空,或者派生最多的类本身没有数据成员,这意味着标准布局类必须采用一种"空基"优化,以及布局的初始部分我B
和Y
以上的实际上是强制性的.