对象创建时的内存分配
本文关键字:内存 分配 创建 对象 | 更新日期: 2023-09-27 18:03:13
当我们实例化类/结构Student时,它将在堆栈和堆中分配多少内存?
我猜id = 4字节引用(32位机器)和名称= 4字节引用和教员顾问= 4字节引用。所以堆栈中总共有12个字节,实际大小将在堆中。这个堆大小可能会有所不同,这取决于我们分配给使用对象obj(Student obj = new Student())的字段(id, name,教员顾问)的值
对于struct也是一样的?
public class Student { int id; string name; Professor facultyAdvisor; }
public struct Student { int id; string name; Professor facultyAdvisor; }
首先注意堆栈和堆是实现细节…物体的大小也是如此。但是在当前的实现中,Student
中字段的所有数据当它是一个类时都在堆上。有对象开销和字段占用的内存,但所有这些都将在堆上。
如果你保持对新实例的引用,并且你将其保存在未捕获的局部变量中,而不是在迭代器块或异步方法中,该引用将在堆栈上(在当前实现中),因此在32位CLR上它将是4字节。
当Student
是一个结构体时,情况有所改变:
- 数据的位置(堆栈或堆)取决于值是如何被使用的-如果它存储在类中的实例变量中,例如,它将与其他数据一起在堆上;如果它在一个局部变量中(同样,未被捕获,不在迭代器块或async方法中),那么它将位于堆栈
- 你没有创建一个单独的对象,只是一个值,所以没有额外的开销-它真的只需要12个字节(假设
Professor
是引用类型)
我有一些你可能会觉得有用的文章/帖子:
- 内存和对象开销(特别是字符串,但也有其他类型)
- 什么去了哪里-堆栈和堆,再次记住这是一个实现细节
编辑:解决Professor
问题,假设Professor
是一个类-除非显式创建Professor
对象,否则Student
中的引用将简单地为空。创建一个新的Student
并不会因为存在一个该类型的字段而自动创建一个新的Professor
。对Professor
的引用只是Student
数据的一部分——它存在于id
所在的地方——所以如果Student
是一个类,那么引用只存在于堆上,如果Student
是一个结构体,那么它取决于Student
的值是在哪里创建的,如上所述。
假设32位CLR(引用在64位CLR上为64位)并且只考虑Student的堆分配
类学生{}类教授{}
- 栈:4字节
- 堆:4字节(int) + 4字节(教授引用)+ 4字节(字符串引用)+ 12字节(对象头)= 24字节
class Student{} struct Professor{}
- 栈:4字节
- 堆:4字节(int) +处理器的大小+ 4字节(字符串引用)+ 12字节(对象头)= ??字节
struct Student{} class教授{}
- 栈:4字节(整型)+ 4字节(字符串引用)+ 4字节(教授引用)= 12字节
- Heap: 0 bytes
struct Student{} struct Professor{}
- 堆栈:4字节(int) + 4字节(字符串引用)+教授的大小= ??字节
- Heap: 0 bytes
您可以使用GC.GetTotalMemory(true)
调用来测量实例化前后的内存消耗,以测量堆分配