C# 内存分配:堆栈还是堆?
我对堆栈与堆之间的内存分配基础感到困惑。根据标准定义(每个人都说的事情),所有值类型将分配到堆栈,引用类型将进入堆C# 内存分配:堆栈还是堆?,c#,.net,stack,heap,C#,.net,Stack,Heap,我对堆栈与堆之间的内存分配基础感到困惑。根据标准定义(每个人都说的事情),所有值类型将分配到堆栈,引用类型将进入堆 现在考虑下面的例子: class MyClass { int myInt = 0; string myString = "Something"; } class Program { static void Main(string[] args) { MyClass m = new MyClass(); } } 现在,
现在考虑下面的例子:
class MyClass
{
int myInt = 0;
string myString = "Something";
}
class Program
{
static void Main(string[] args)
{
MyClass m = new MyClass();
}
}
现在,在c#中内存分配将如何进行?MyClass
(即m
)的对象是否将完全分配给堆?也就是说,intmyint
和stringmystring
都将进入堆
或者,对象将分为两部分,并将分配给两个内存位置,即堆栈和堆?
m
在堆上分配,其中包括myInt
。在堆栈上分配原语类型(和结构)的情况是在方法调用期间,方法调用为堆栈上的局部变量分配空间(因为这样更快)。例如:
class MyClass
{
int myInt = 0;
string myString = "Something";
void Foo(int x, int y) {
int rv = x + y + myInt;
myInt = 2^rv;
}
}
rv
,x
,y
都将在堆栈上<代码> MyTime/Cuff>是堆上的某个地方(必须通过<代码>这个指针)访问。 < P>您应该考虑对象被分配为实现细节的问题。对你来说,一个对象的比特存储在什么地方并不重要。对象是引用类型还是值类型可能很重要,但在开始优化垃圾收集行为之前,您不必担心它将存储在何处
虽然在当前的实现中引用类型总是在堆上分配,但值类型可以在堆栈上分配,但不一定。只有当值类型是未包含在引用类型中且未在寄存器中分配的未装箱非转义局部或临时变量时,才会在堆栈上分配该值类型
- 如果值类型是类的一部分(如示例中所示),那么它将在堆中结束
- 如果它被装箱了,它最终会被放在堆上
- 如果它在一个数组中,它将在堆中结束
- 如果它是一个静态变量,那么它将在堆中结束
- 如果它被一个闭包捕获,那么它最终将被放在堆上
- 如果在迭代器或异步块中使用它,它将在堆中结束
- 如果它是由不安全或非托管代码创建的,则可以在任何类型的数据结构(不一定是堆栈或堆)中进行分配
- 也许是最好的一个:
- 第1部分:
- 第2部分:
- 第3部分:
- 第4部分:
引用类型通过引用传递(AgaIn不考虑引用将在将来的版本中再次存储地址,它可以存储在其他一些数据结构上)。 那么你的情况呢
myInt是一个int,它被封装在一个类中,这个类当然是一个引用类型,因此它将绑定到将存储在“HEAP”上的类的实例 我建议,你可以开始阅读埃里克·利珀斯写的博客每次在内存中创建对象时,它都会进入称为堆的内存区域。基本变量如下 如果int和double是本地方法变量,则在堆栈中分配;如果int和double是成员变量,则在堆中分配 变量。在方法中,当调用方法时,局部变量被推入堆栈 当方法调用完成时,堆栈指针将递减。在多线程应用程序中,每个线程 将有自己的堆栈,但将共享同一堆。这就是为什么在代码中要小心避免任何错误 堆空间中的并发访问问题。堆栈是线程安全的(每个线程都有自己的堆栈),但是 堆不是线程安全的,除非通过代码进行同步保护 此链接也很有用Stack
堆栈
是一块内存,用于存储局部变量
和参数
。堆栈在逻辑上随着函数的输入和退出而增长和收缩
考虑以下方法:
public static int Factorial (int x)
{
if (x == 0)
{
return 1;
}
return x * Factorial (x - 1);
}
using System;
using System.Text;
class Test
{
public static void Main()
{
StringBuilder ref1 = new StringBuilder ("object1");
Console.WriteLine (ref1);
// The StringBuilder referenced by ref1 is now eligible for GC.
StringBuilder ref2 = new StringBuilder ("object2");
StringBuilder ref3 = ref2;
// The StringBuilder referenced by ref2 is NOT yet eligible for GC.
Console.WriteLine (ref3); // object2
}
}
这个方法是递归的,这意味着它调用自己每次输入该方法时,会在堆栈上分配一个新的int,每次退出该方法时,会取消分配int
堆
- 堆是
(即对象
)所在的内存块。每当创建一个新对象时,就会在堆上分配它,并返回对该对象的引用。在程序执行期间,当创建新对象时,堆开始填满。运行时有一个垃圾收集器,它定期从堆中释放对象,因此程序不会在内存不足的情况下运行。对象符合释放条件引用类型实例