当类存储在堆(.NET)上时,为什么结构存储在堆栈中?

ich*_*ban 26 .net c#

我知道类和结构之间的区别之一是结构实例存储在堆栈上,类实例(对象)存储在堆上.

由于类和结构非常相似.有人知道这种特殊区别的区别吗?

Mar*_*ell 39

(编辑以涵盖评论中的要点)

要强调:值类型和引用类型之间存在差异和相似之处,但这些差异与堆栈与堆无关,而与复制语义与引用语义无关.特别是,如果我们这样做:

Foo first = new Foo { Bar = 123 };
Foo second = first;
Run Code Online (Sandbox Code Playgroud)

然后是"第一"和"第二"谈论相同的副本Foo?还是不同的副本?恰好相反,堆栈是一种将值类型作为变量处理的方便有效的方法.但这是一个实现细节.

(结束编辑)

重新整个"值类型进入堆栈"的事情...... - 值类型并不总是在堆栈上;

  • 如果他们是一个班级的领域
  • 如果他们是盒装的
  • 如果他们是"捕获变量"
  • 如果它们在迭代器块中

然后他们进入堆(最后两个实际上只是第一个的异国情况)

class Foo {
    int i; // on the heap
}

static void Foo() {
    int i = 0; // on the heap due to capture
    // ...
    Action act = delegate {Console.WriteLine(i);};
}

static IEnumerable<int> Foo() {
    int i = 0; // on the heap to do iterator block
    //
    yield return i;
}
Run Code Online (Sandbox Code Playgroud)

此外,Eric Lippert(如前所述)在此主题上有一篇很棒的博客文章

  • 我不确定它们"非常相似" - 但重点是; 它们之间的差异与堆栈和堆很少有关,而且与copy-semantics和reference-semantics有关 (4认同)

mqp*_*mqp 10

在实践中,出于某些目的能够在堆栈上分配内存是有用的,因为这些分配非常快.

但是,值得注意的是,没有任何基本保证将所有结构放置在堆栈上.Eric Lippert最近写了一篇关于这个主题的有趣博客文章.

  • 分配的相对速度并不特别相关.这是*deallocation*在堆栈上很便宜.通过移动堆栈指针来完成堆栈上的值的重新分配,这需要大约一纳秒.在堆上重新分配值需要垃圾收集,这可能需要任意长时间. (9认同)

Eri*_*ert 9

这是一个很好的问题; 我没有在Marc Gravell链接的文章中介绍它.这是第二部分:

http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx


Bur*_*gan 7

每个进程都有一个数据块,由两个不同的可分配内存段组成.这些是堆栈和堆.Stack主要用作程序流管理器,并保存局部变量,参数和返回指针(在从当前工作函数返回的情况下).

与值类型(如结构体)(或基本类型 - 整数,字符等)相比,类非常复杂并且大多数都是非常大的类型.由于堆栈分配应该专注于程序流的效率,因此它不能保持最佳环境.大物件.

因此,为了满足这两个期望,这个分离的架构出现了.

  • .Net应用程序和大多数其他应用程序都有堆栈和堆,但并非所有程序都有堆栈和堆.例如,无堆栈python根本就没有堆栈.它使用堆分配帧的链接列表进行方法调用... (2认同)
  • 这是一个与.NET相关的问题.我用"每一个"的唯一原因. (2认同)