我知道struct是一个值类型,这意味着它在堆栈上定义。
但我可以做A a = new A(); (当然是我的结构)。它在堆上定义,只有引用变量在堆栈上。
请你解释一下这个。
答案 0 :(得分:4)
值类型存储在堆栈有时。这是一个复杂的主题,通常变量(堆栈或堆)的确切存储与编程问题无关。值和引用类型之间的真正区别在于它们的行为(例如,值类型总是按值按值复制)。
Eric Lippert详细介绍了这个问题:
答案 1 :(得分:2)
存储局部变量的地方是实现细节 简单的局部变量通常存储在CPU寄存器和/或堆栈中。
如果在闭包中捕获它们,它们将被重写为堆分配对象中的成员。那是因为lamda可能比创建函数更长,因此它使用的变量也必须能够存活足够长的时间。
与C#中的C ++不同, new
并不意味着堆分配。它只是调用构造函数的语法。
在值类型上调用new
也没有新的贴图的语义。它具有构造实例某处然后将其复制到目标变量的语义。
在我的心智模型中,有两种类型的存储:
您的示例属于第一种存储,因为您使用的是值类型。
答案 2 :(得分:1)
您的代码(A a = new A();)创建并初始化结构。如果它是局部变量,则在堆栈上初始化。如果它是一个成员变量,它将作为对象的一部分在堆上初始化。使用“new”并不一定意味着在C#/ .NET中进行堆分配。这取决于具体情况。
答案 3 :(得分:1)
值类型生活在“堆栈”中的原始假设是不正确的。但是,Eric Lippert透露了 The Truth About Value Types :
- 通常声明不正确:语句应该是“值类型可以存储在堆栈中”,而不是更常见的“值类型总是存储在堆栈“。
- 几乎总是无关。我们努力创建一个托管环境,在这种环境中,不同类型的存储之间的区别对用户是隐藏的。与某些语言不同,在这些语言中,出于正确原因,您必须知道特定存储是在堆栈还是堆中。
- 不完整。 引用怎么样?引用既不是值类型也不是引用类型的实例,但它们是值。他们必须存放在某个地方。他们是在堆栈还是堆上?为什么没有人谈论过它们?仅仅因为它们在C#类型系统中没有类型就没有理由忽略它们。
醇>
答案 4 :(得分:0)
但我可以做A a = new A(); (当然是我的结构)。它在堆上定义,只有引用变量在堆栈上。
如果A
是您所说的值类型,并且a
是本地方法,则它将在堆栈上分配。 除非在闭包中使用 a
,否则它将被分配为编译器生成的类的堆分配对象的一部分。
如果您想进行进一步分析,则必须发布A
类型的定义以及定义此变量的整个方法。