C# 对象创建时的内存分配
当我们实例化类/结构Student时,它将在堆栈和堆中分配多少内存 我猜id=4字节引用(32位机器),name=4字节引用,facultyAdvisor=4字节引用。所以堆栈中总共有12个字节,实际大小将在堆中。此堆大小可能会有所不同,这取决于我们为使用对象obj(Student obj=new Student())的字段(id、name、facultyAdvisor)指定的值 struct也是如此,对吗C# 对象创建时的内存分配,c#,C#,当我们实例化类/结构Student时,它将在堆栈和堆中分配多少内存 我猜id=4字节引用(32位机器),name=4字节引用,facultyAdvisor=4字节引用。所以堆栈中总共有12个字节,实际大小将在堆中。此堆大小可能会有所不同,这取决于我们为使用对象obj(Student obj=new Student())的字段(id、name、facultyAdvisor)指定的值 struct也是如此,对吗 public class Student { int id; string name;
public class Student { int id; string name; Professor facultyAdvisor; }
public struct Student { int id; string name; Professor facultyAdvisor; }
您可以使用
GC.GetTotalMemory(true)
调用来测量实例化前后的内存消耗,以测量堆分配首先请注意。。。对象的大小也是如此。但是在当前的实现中,Student
中的字段的所有数据(当它是一个类时)都在堆上。有一个对象开销以及字段占用的内存,但所有这些都将在堆上
如果保留对新实例的引用,并且将其保留在未捕获的局部变量中,而不是在迭代器块或异步方法中,则该引用将位于堆栈上(在当前实现中),因此在32位CLR上为4字节
当Student
是一个结构时,情况会有所变化:
- 数据(堆栈或堆)的位置取决于值的使用方式——例如,如果它存储在类中的实例变量中,它将与其他数据一起位于堆上;如果它在局部变量中(同样,未捕获,不在迭代器块或异步方法中),那么它将在堆栈上
- 您没有创建一个单独的对象,只是一个值,因此没有额外的开销-实际上只需要12个字节(假设
是一个引用类型)Professor
- (特别是字符串,但也包括其他类型)
- -堆栈和堆,再次记住这是一个实现细节
Professor
问题,假设Professor
是一个类-除非明确创建Professor
对象,否则Student
中的引用将为空。创建一个新的Student
不会因为存在一个该类型的字段而自动创建一个新的Professor
。对Professor
的引用只是Student
数据的一部分-它存在于id
所在的任何地方-因此如果Student
是一个类,那么引用只存在于堆上,如果Student
是一个结构,那么它取决于Student
值的创建位置,如上所列。假设32位CLR(在64位CLR上引用为64位),并且只考虑学生的堆分配
班级学生{}班级教授{}
- 堆栈:4字节
- 堆:4字节(int)+4字节(Professor Reference)+4字节(string Reference)+12字节(objectheader)=24字节
- 堆栈:4字节
- 堆:4字节(int)+处理器大小+4字节(字符串引用)+12字节(对象头)=??字节
- 堆栈:4字节(整数)+4字节(字符串引用)+4字节(教授引用)=12字节
- 堆:0字节
- 堆栈:4字节(int)+4字节(字符串引用)+教授大小=??字节
- 堆:0字节