内存中的自定义结构类型

时间:2014-10-20 17:25:56

标签: c# struct

我知道class类型或引用类型在堆栈内存中有引用,而值类型(如果定义为局部变量)也驻留在堆栈中。但是,我知道intdouble等类型如何驻留在堆栈中,但不太确定自定义结构类型如何位于堆栈中。例如:

public struct Employee
{
   public int Age {get;set;}
   public string Name {get;set;}
}

static void Main(params string[] args)
{
   Employee employee; // How does it look like in stack at the moment of declaration?
   employee = new Employee(); // And during this line?
   employee.Name = "Hello World"; // And during this statement?
}

你能解释employee结构如何驻留在内存中吗?我可以想象AgeName与其他变量一样,但Employee如何将它们封装在堆栈中?一个很好的详细解释会非常好。

3 个答案:

答案 0 :(得分:4)

当所有值类型(即结构)是局部变量或按值参数(即通常的参数类型)时,它们仅存储在堆栈 中。这包括int,bool等和自定义结构。回答“如何”这种情况只是知道内存存储一般如何工作的问题,但基本思想是它与引用类型完全相同,除了计算机使用称为“堆栈”的内存区域而不是内存区域称为“堆”。这两个领域之间的主要区别在于如何管理区域的使用。否则,它们都只是计算机内存中的位置并且工作方式相同(即指向一个指针的指针与指向另一个指针的指针相同)。

有关引用类型与值类型的更多信息,特别是为什么您不应该真正关心存储值类型的位置(特别是因为当引用类型的一部分,它们仍然存储在堆中时),请参阅此类来自Eric Lippert的已知文章: http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

答案 1 :(得分:2)

在正常情况下,你不应该担心结构在内存中是如何布局的。 CLR决定它自己的。如果需要特定布局,可以使用StructLayout属性控制它。

您的案例中的new关键字只提供了在堆上新建类对象时使用的相同语义。

Employee employee;
employee = new Employee();

等于写作:

var employee = new Employee();

实际上,如果你不使用new运算符,它将在下一行报告:

  

..使用未分配的局部变量employee

分配源结构的所有字段的结构变量副本,但事实并非如此,因为它只是一个初始化表达式,并且没有理由复制任何内容。 构造函数只是作用于驻留在堆栈中的新对象的字段及其字段值,就像您声明了一组类似的局部变量一样。在这种情况下,它只是使用默认值对fileds进行初始化:对于int为零,对于字符串为null。

在本声明中:

employee.Name = "Hello World";

它调用setter函数,后者又将值赋给私有字段。如果使用优化进行编译,则会内联此setter函数。

答案 2 :(得分:2)

正如其他人所说,你几乎不需要担心堆栈在内存中的实际布局,或者就此而言,是否完全使用堆栈。请记住,寄存器通常也用于实现临时存储。

抖动在堆栈上布置记录的方式取决于实现,并且可能因机器而异。要了解程序如何在机器内存中进行布局:编译,调试,进入汇编级调试,并检查堆栈寄存器周围的内存。

,请注意当您从一个语句转到另一个语句时,该内存会如何变化。