7
class foo { }

writeln(foo.classinfo.init.length); // = 8 bytes

class foo { char d; }

writeln(foo.classinfo.init.length); // = 9 bytes

d 实际上是否在这 8 个字节中存储了任何内容,如果是,是什么?这似乎是一种巨大的浪费,如果我只是包装一些值类型,那么该类会使程序显着膨胀,特别是如果我使用了很多它们。char 变大 8 倍,而 int 变大 3 倍。

结构的最小大小为 1 个字节。

4

4 回答 4

9

在 D 中,对象有一个包含 2 个指针的标头(因此它可能是 8 字节或 16 字节,具体取决于您的架构)。

第一个指针是虚方法表。这是一个由编译器生成的填充了函数指针的数组,因此可以进行虚拟调度。同一个类的所有实例共享同一个虚方法表。

第二个指针是监视器。它用于同步。不确定该字段是否永远保留在这里,因为 D 强调本地存储和不变性,这使得许多对象上的同步毫无用处。由于此字段比这些功能更早,因此它仍然存在并且可以使用。但是,它可能会在未来消失。

对象上的此类标头非常常见,例如,您会在 Java 或 C# 中找到相同的标头。您可以在这里查看更多信息:http ://dlang.org/abi.html

于 2012-12-05T20:19:50.187 回答
9

D 在每个类实例中使用两个机器词:

  1. 指向虚函数表的指针。这包含虚拟方法的地址。第一个入口指向类的classinfo,动态转换也使用它。

  2. 允许synchronized(obj)语法的监视器记录在这里

这些字段在此处(向下滚动到“类属性”)和此处(向下滚动到“类”)的 D 文档中进行了描述。

于 2012-12-05T20:19:54.387 回答
0

我不知道 D 的细节,但是在 Java 和 .net 中,每个类对象都包含有关其类型的信息,并且还包含有关它是否是任何监视器锁的目标、是否有资格进行终结清理以及各种其他事情。拥有所有对象存储此类信息的标准方法可以使语言和/或框架的用户和实现者在许多事情上更加方便。顺便说一句,在 .net 的 32 位版本中,每个对象的开销为 8 个字节,但最小对象大小为 12 个字节。这个最小值源于这样一个事实,即当垃圾收集器移动对象时,

编辑 如果你想使用一个类,因为你需要能够持久化对数据项的引用,空间是非常宝贵的,并且你的使用模式是这样的,你会知道数据项何时仍然有用以及何时过时,您可以定义一个结构数组,然后将索引传递给数组元素。可以编写代码来非常有效地处理这个问题,而且开销基本上为零,前提是您的程序结构允许您确保每个被分配的项目都只被释放一次,并且一旦被释放就不会被使用。

如果您无法轻易确定对对象的最后一个引用何时超出范围,那么 8 个字节将是一个非常合理的开销水平。我希望大多数框架会强制对象在 32 位边界上对齐(所以我很惊讶添加一个字节会将大小推到九而不是十二)。如果一个系统将有一个比 Commodore 64(*) 工作得更好的垃圾收集器,那么每个对象需要绝对最小的一点开销来指示哪些东西被使用,哪些东西没有被使用。此外,除非想要为可以包含补充信息的对象和不能包含补充信息的对象设置单独的堆,否则每个对象要么包含用于补充信息指针的空间,要么包含用于所有补充信息的空间(锁定、放弃通知请求等)。虽然在某些情况下为两类对象设置单独的堆可能是有益的,但我怀疑这些好处通常会证明增加的复杂性是合理的。

(*) Commodore 64 垃圾收集器通过从内存顶部向下分配字符串来工作,而变量(未经过 GC 处理)是自下而上分配的。当内存已满时,系统将扫描所有变量以查找对存储在最高地址的字符串的引用。然后该字符串将被移动到内存的最顶部,并且对它的所有引用都将被更新。然后,系统将扫描所有变量以在它刚刚移动的地址下方的最高地址处找到对字符串的引用,并更新对该字符串的所有引用。该过程将重复,直到找不到更多要移动的字符串为止。该算法不需要将任何额外的数据与字符串一起存储在内存中,但它当然很慢。Commodore 128 垃圾收集器与 GC 空间中的每个字符串一起存储一个指向变量的指针,该变量包含一个引用和一个长度字节,可用于在 GC 空间中查找下一个较低的字符串;因此,它可以检查每个字符串以确定它是否仍在使用,如果是,则将其重新定位到内存的顶部。快得多,但代价是每个字符串需要三个字节的开销。

于 2012-12-05T19:50:46.887 回答
-2

您应该查看各种类型的存储要求。每条指令、存储分配(即:变量/对象等)都会占用特定数量的空间。在 c# 中,一个 Int32 类型的整数对象应该以 4 个字节(32 位)的形式存储整数信息。它也可能有其他信息,因为它是一个对象,但您的字符数据类型可能只需要 1 个字节的信息。如果你在课堂上有类似 for 或 while 的结构,这些东西也会占用空间,因为这些东西中的每一个都在告诉你的班级做某事。类本身需要在内存中创建许多指令,这将占 8 个初始字节。

参加汇编语言课程。您将了解所有您想知道的内容,然后了解为什么您的程序在编译时会使用多少内存或占用多少存储空间。

于 2012-12-05T19:50:57.523 回答