内存分配:堆栈vs堆?

我对堆栈与堆之间的内存分配基础感到困惑。 按照标准定义(每个人都说的事情),所有的值类型将被分配到堆栈,并且引用类型将被放入堆中

现在考虑下面的例子:

class MyClass
{
    int myInt = 0;    
    string myString = "Something";
}

class Program
{
    static void Main(string[] args)
    {
       MyClass m = new MyClass();
    }
}

现在,如何在c#中发生内存分配? MyClass的对象(即m )是否会被完全分配给堆? 也就是说, int myIntstring myString都会去堆?

或者,该对象将被分成两部分,并将分配给这两个内存位置,堆栈和堆?


m在堆上分配,并且包含myInt 。 原始类型(和结构体)在堆栈上分配的情况是在方法调用期间,它为堆栈中的局部变量分配空间(因为速度更快)。 例如:

class MyClass
{
    int myInt = 0;

    string myString = "Something";

    void Foo(int x, int y) {
       int rv = x + y + myInt;
       myInt = 2^rv;
    }
}

rvxy都会在堆栈中。 myInt是堆中的某个地方(并且必须通过this指针访问)。


您应该考虑将对象分配为实现细节的问题。 对于存储对象的位的确切位置无关紧要。 可能很重要的一个对象是引用类型还是值类型,但是您不必担心它将存储在何处,直到您开始优化垃圾回收行为。

虽然引用类型总是在当前实现中的堆上分配,但值类型可能会分配到堆栈上 - 但不一定。 值类型仅在堆栈上分配,因为它是未包含的非转义本地或临时变量,该变量未包含在引用类型中,也未分配到寄存器中。

  • 如果一个值类型是一个类的一部分(如你的例子),它将在堆上结束。
  • 如果它是盒装的,它将在堆上结束。
  • 如果它在数组中,它将最终堆在堆上。
  • 如果它是一个静态变量,它将最终堆在堆上。
  • 如果它被关闭捕获,它将最终堆在堆上。
  • 如果它在迭代器或异步块中使用,它将最终堆在堆上。
  • 如果它是由不安全或不受管理的代码创建的,它可以分配到任何类型的数据结构中(不一定是堆栈或堆)。
  • 有什么我错过了吗?

    当然,如果我没有链接到Eric Lippert关于这个主题的帖子,我将会失职:

  • 堆栈是一个实现细节,第一部分
  • 该堆栈是一个实现细节,第二部分
  • 也许是最好的:关于价值类型的真理

  • “所有VALUE类型将被分配到堆栈”是非常非常错误的; 结构变量可以作为方法变量驻留在堆栈上。 但是,某种类型的字段与该类型相同。 如果某个字段的声明类型是一个类,则这些值作为该对象的一部分存储在堆中。 如果一个字段的声明类型是一个结构体,那么这些结构体就是那个结构体所在的结构体的一部分。

    即使方法变量可以放在堆上,如果它们被捕获(lambda / anon-method),或者(例如)迭代器块的一部分。

    链接地址: http://www.djcxy.com/p/14533.html

    上一篇: Memory allocation: Stack vs Heap?

    下一篇: Does delete call the destructor?