引用和对象占用的内存空间是多少



当我声明变量并为该变量创建对象时,后台(在内存的情况下)会发生什么。引用变量存储在任何地方,以何种格式存储,以及该变量如何指向堆上的内存。请在评论中澄清以下疑虑。

例如

ClassA instance;       // Where this variable store and how much memory occupies
instance=new ClassA(); //How instance variable points to memory

编辑

如果我的程序包含这么多未使用的变量,会对我的程序内存产生什么影响。

实例变量在运行时只是一个指针,它指向GC堆中分配的对象。变量可以存在于任何地方,堆栈、CPU寄存器、堆上的另一个对象内部,如果是静态的,则可以存在于加载程序堆中。

垃圾收集器的重要之处在于它能够在垃圾收集过程中找到这个指针。因此可以看到对象仍然被引用,并且可以在压缩堆时调整指针值。当引用在另一个对象内部是静态的时,这是相当直接的。当它在堆栈或寄存器上时,抖动会提供足够的信息让GC找到它

引用变量以内联方式存储。如果它是局部变量,则在堆栈上分配;如果它是类的成员,则作为堆上对象的一部分分配。

类的实例总是在堆上分配的。

引用只是一个指针,但特别的是垃圾收集器知道引用。因此,引用使用指针使用的空间量。在32位进程中,它使用4个字节,在64位进程中使用8个字节。

引用本身的本地变量的存储位置取决于平台(抖动可以选择存储位置。)通常,它将在定义本地的方法的调用堆栈上的内存中或CPU寄存器中。大小也取决于平台,但对于32位体系结构通常为4字节,对于64位体系结构则为8字节。

引用可以"指向"堆,也可以不"指向"该堆。最好将其视为一个不透明的引用标识符,可用于访问对象。基础指针可以在运行时更改。

对于未使用的变量,优化编译器通常会完全消除任何未使用的局部变量,因此对运行时性能没有任何影响。此外,您所说的存储引用的开销类型对于现代平台来说是很小的。

如果你需要关于这方面的答案,那么我建议你去看看《CLR via C#》,这是一本关于CLR如何工作的书,其中包含了很多关于这一点的信息。

为了回答你的问题,你需要思考很多事情来回答这个问题。

例如,您需要将每个方法的指令存储在类中。当类首次加载时,它将有效地成为指向.Net IL指令的指针。当应用程序首次需要该方法时,它将被JIT编译为处理器的实际指令,并存储在内存中。

然后您就有了类字段的静态存储,每个类只存储一次。

由于各种原因,.Net中实例化的每个类都需要存储,但不限于继承、垃圾收集、布局等。然后,您就可以存储各种引用,这些引用可以保存到对象,而对象本身将进行存储。

如果内存确实对您正在做的事情至关重要,那么C#可能不是您应用程序的最佳选择。否则,只需享受使用.NET带来的生产力优势,并接受这种易用性带来的内存使用成本和C/C++应用程序的低性能(在某些情况下)。

最新更新