C# 引用类型位于堆上,值类型位于堆栈上
在阅读“C#indepth”时,我浏览了“引用类型位于堆上,值类型位于堆栈上”一节 现在我能理解的是(主要是ref类型): 我只是想澄清一下我的假设是否正确。谢谢 编辑: 我应该使用diff变量,我认为这造成了混乱。所以我修改了代码 编辑: 是的,正如乔恩提到的-这是一个神话,我应该提到。我的道歉。C# 引用类型位于堆上,值类型位于堆栈上,c#,C#,在阅读“C#indepth”时,我浏览了“引用类型位于堆上,值类型位于堆栈上”一节 现在我能理解的是(主要是ref类型): 我只是想澄清一下我的假设是否正确。谢谢 编辑: 我应该使用diff变量,我认为这造成了混乱。所以我修改了代码 编辑: 是的,正如乔恩提到的-这是一个神话,我应该提到。我的道歉。 整个“堆上的引用类型,堆栈上的值类型”不仅是一种不好的看待它的方式,但是它也错了。c留在堆栈上,因为至少是一个值类型,而a在托管堆中,因为是引用类型的字段我可能是一个有点有用的抽象概念,可以在脑海中
整个“堆上的引用类型,堆栈上的值类型”不仅是一种不好的看待它的方式,但是它也错了。
c
留在堆栈上,因为至少是一个值类型,而a
在托管堆中,因为是引用类型的字段我可能是一个有点有用的抽象概念,可以在脑海中了解幕后发生的事情。但在任何当前发布的JIT编译器版本中都不是这样。这可能是问题的症结所在,实际的分配位置是JIT编译器实现的细节
至少有六个地方的值类型值可以与主流(x86和x64)抖动共存:
- 在堆栈帧中,通过局部变量声明或方法调用将
- 在CPU寄存器中,JIT在发布构建中执行的一种非常常见的优化。用于将参数传递给方法,前两个x86,四个用于x64。和局部变量(如果可能)
- 在FPU堆栈上,x86抖动用于浮点值
- 在GC堆上,当值是引用类型的一部分时
- 在AppDomain的加载程序堆上,当变量声明为静态时
- 当变量具有[ThreadStatic]属性时,在线程本地存储中
- 是的,“a”很可能存储在GG堆上
- “x”总是在x86和x64上的CPU寄存器中传递。“y”将位于x64上的CPU寄存器中,x86上的堆栈
- “c”很可能根本不存在,因为代码无效,所以被JIT编译器删除
换句话说,引用类型指向的>对象<位于堆上,而堆栈上的指针本身就是指针。当程序将指针从堆栈中弹出时,会发生内存泄漏,但堆中的内存尚未释放以供使用——如果对其位置的引用丢失,您如何知道要释放哪些内存?好吧,C/C++不行,在引用从堆栈中弹出并永远丢失之前,您必须自己做,但这就是现代语言以其奇特的“垃圾收集堆”出现的原因。与隐式清理任何分配的堆内存相比,显式清理任何已分配的堆内存更可取,因为这样做“更便宜”(就CPU资源而言)。引用Jon Skeet的话,说明引用和值类型在.Net应用程序中的存储方式和位置: 变量的内存插槽存储在堆栈或 堆它取决于声明它的上下文:
class Program
{
int a = 5; // stored in heap
public void Add(int x, int y) // x,y stored in stack
{
int c = x + y; // c stored in stack
}
}