.NET 中具有深度继承的类的内存分配

Posted

技术标签:

【中文标题】.NET 中具有深度继承的类的内存分配【英文标题】:Memory allocation for a class that has deep inheritance in .NET 【发布时间】:2011-01-23 20:50:41 【问题描述】:

如果我有 A, B, C, D, E 类和 X, Y, Z 之类的接口,并为这样的系统建模:

class B : A, X
class C : B, Y
class D : C, Z
class E : D

如果A 是一个抽象基类并且E 是感兴趣的类,那么当我创建E 的一个实例时,它是否会在E 之外又创建A, B, C, D, X, Y, Z 的实例?

如果是这样,这会产生巨大的性能开销吗?不是内存,而是运行时和 GC。

【问题讨论】:

【参考方案1】:

是的,它会创建 A、B、C 和 D 的“嵌入式”实例 不,它不会创建 X、Y 和 Z 的实例(因为它们是接口)

内存分配或 GC(ABCD)没有额外的开销,因为 E 的实例被分配为 1 个块。任何运行时开销都将完全取决于所涉及的构造函数。

总会有一个构造函数链(从 E 到 A)在执行,可能是默认构造函数,但也可以在 1 级调用多个构造函数。

【讨论】:

抱歉,没有继承创建的实例! @Obalix,注意嵌入的引号。但是,是的,最终只涉及 1 个实例。 感谢 Henk,所以在这种情况下,例如,如果您要将这些类合并为一个没有继承的类,它们在内存、GC 和运行时性能方面是否几乎相同? 【参考方案2】:

继承扩展了 Type 并且不创建实例。您有一个 E 实例,其中包含由 A、B、C、D 和 E 定义的数据。它提供由这些类以及接口 X、Y 和 Z 定义的方法和属性访问器。

【讨论】:

【参考方案3】:

它将创建一个对象 - E 的一个实例 - 但这将包括类层次结构中声明的所有字段。 (接口不能声明字段,因此它们与对象本身的数据无关。)只有字段(以及影响布局的任何属性,诚然)才会对对象占用的内存做出贡献。

对 E 实例的引用可以“转换”为 A、B、C、D、X、Y 或 Z 类型的引用,作为保持身份的引用转换 - 即它仍然是对同一个对象。

【讨论】:

谢谢乔恩。当您将 E 转换为上述任何一种时,它会创建一个新实例吗?我认为它适用于基类,对吧?但是对于接口呢? 另外,例如,如果您要将这些类合并为一个没有继承的类,它们在内存、GC 和运行时性能方面是否几乎相同? @Joan:你不转换E的实例,只是对实例的引用'转换',这很便宜。 谢谢 Henk,它是如何工作的?你的意思是引用指针被转换为另一种类型?实际上我认为所有的引用指针都是一样的,即没有关于它所指向的信息。 @Joan:在编译时它有很多关于它所指向的信息,即使在非托管语言中也是如此。 .NET 将其扩展到运行时,CLR 验证正确的转换。但是没有物理转换。

以上是关于.NET 中具有深度继承的类的内存分配的主要内容,如果未能解决你的问题,请参考以下文章

何时为 C++ 中的类的成员函数分配内存空间?

Java继承内存分配

三:JVM对象创建与内存分配机制深度剖析

对象创建方法,对象的内存分配,对象的访问定位

java内存区域

类的加载次序与继承