当前位置: 首页 > 知识库问答 >
问题:

空派生优化

孙鑫鹏
2023-03-14

大多数C程序员都知道空基类优化是一种技术/习惯用法。空的子类会发生什么?例如

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相似吗?

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

共有1个答案

秦博达
2023-03-14

该标准本身不包含“空基类”大小写。相反,它说(参见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的地址,A-b的子对象的地址(即

唯一不起作用的是这个:

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

我所说的“等效”是指最明智、最节省空间的实现。

一个更有趣的案例如下:

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

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

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

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

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

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

 类似资料:
  • 问题内容: 我知道如何使用派生表,但是我仍然可以真正看到使用它们的任何真正优势。 例如,在下面的文章http://techahead.wordpress.com/2007/10/01/sql-derived- tables/中 ,作者试图展示使用派生表的查询优于没有示例的查询的优点,我们要生成一个报告,以显示每个客户在1996年下的订单总数,我们希望该结果集包括所有客户,包括当年未下订单的客户和从

  • 通过 #[derive] 属性,编译器能够提供一些对于 trait 的基本实现。如果需要一个更复杂的业务,这些 trait 仍然可以手动实现。(原文:The compiler is capable of providing basic implementations for some traits via the #[derive] attribute. These traits can stil

  • 但是,如果实用工具类是从Qt类派生的,我会出现链接错误。我认为问题出在Q_OBJECT宏上,如果我不添加它,我就不会得到错误。但是在任何Qt派生类中都必须/建议使用Q_OBJECT宏。 我怎样才能避免这个ISUE?有没有其他方法来拥有一个具有文件作用域的实用程序类? 用于显示错误的简单示例:CMyClass类使用从QWidget派生的实用工具类(名为CUtility)。 错误有: LNK2001:

  • 问题内容: 假设您有这样的查询… 可以将多个人分配给给定任务。该查询的目的是显示每个任务一行,但将分配给该任务的人员显示在单个列中 现在…假设你有正确的指标设置上,和。连接到派生表时,MySQL Optimizer仍将不使用TaskID索引。WTF?!?!? 因此,我的问题是…如何使此查询使用task_assigned_users.TaskID上的索引?临时表是la脚的,所以如果这是唯一的解决方案

  • 问题内容: 我需要帮助,以了解如何在Go中妖魔化一个流程。 如果在命令行上启动此代码,则程序将返回控制权,但仍与cmd连接。关闭cmd将关闭程序。 如何将其与cmd分离?新增: 导致此错误:错误内存指针“恐慌” 问题答案: 我在“ golang-nuts”中询问,发现golang具有链接选项:

  • 数据结构是指若干个数据的连接方式,一个复杂的数据往往是由若干个不同类型数据形成的结构。派生类型是指用户利用FORTRAN系统内部类型,如数值型、逻辑型、字符型等自行设计出一个新的数据类型,它们实际上是由内部类型数据形成的某种结构。本章主要目的是学会按复杂数据的客观结构形态,由程序员定义出一种派生类型,再结合上将在后面叙述的模块后,可将该类型必需的操作写成内部子程序,连同派生类型一起写在模块中,供程