C# .NET-存储在堆或堆栈地址空间中的函数变量?

C# .NET-存储在堆或堆栈地址空间中的函数变量?,c#,.net,memory,heap-memory,stack-memory,C#,.net,Memory,Heap Memory,Stack Memory,我在一次考试中遇到了以下问题: 当程序调用函数时,使用哪种类型的数据结构 为该函数中的变量分配的内存 堆 排队 后进先出 堆叠 根据测试,HEAP是正确答案,尽管我选择了STACK 有人能解释一下原因吗 提前感谢。好吧,局部变量和参数存储在堆栈上,而不是堆上。对于本地值类型,这意味着值本身存储在堆栈上。对于本地引用类型,只有引用将位于堆栈上 然而,为了得到更深入的解释,我建议阅读Erik Lippert的一篇非常好的博文(他在评论中已经指出了这篇博文): 这是一个写得很差的问题,我想知道写这个问

我在一次考试中遇到了以下问题:

当程序调用函数时,使用哪种类型的数据结构 为该函数中的变量分配的内存

  • 排队
  • 后进先出
  • 堆叠
  • 根据测试,HEAP是正确答案,尽管我选择了STACK

    有人能解释一下原因吗


    提前感谢。

    好吧,局部变量和参数存储在堆栈上,而不是堆上。对于本地值类型,这意味着值本身存储在堆栈上。对于本地引用类型,只有引用将位于堆栈上


    然而,为了得到更深入的解释,我建议阅读Erik Lippert的一篇非常好的博文(他在评论中已经指出了这篇博文):

    这是一个写得很差的问题,我想知道写这个问题的人的能力如何。正如bejger所回答的,在大多数语言中,局部变量(和函数参数)存储在“堆栈”上。在C#或Java等参考语言中,对象存储在“堆”中,引用存储在“堆栈”上的对象(指针)。这个问题值得怀疑,因为它没有指定语言或确切的场景。此外,我根本不会将堆和堆栈称为“数据结构”。在这种情况下,它们是内存分配方案,而不是数据结构。

    首先,C#没有“函数”;它有“方法”

    您所说的“在哪种类型的数据结构中为该函数中的变量分配了内存”是什么意思

    注:为了记录在案,“后进先出”是一种访问策略(后进先出), 不是数据结构。通常,人们将一个堆栈称为后进先出堆栈。但我离题了

    正确的答案通常是

    • “视情况而定”,或
    • “堆栈和堆”
    局部变量(仅存在于方法调用上下文中的变量)的插槽在方法调用期间的堆栈框架内分配,方法调用位于程序堆栈中

    如果变量是引用类型,则该插槽是对实际对象实例的引用,当/如果实例化该实例时,将从堆中为其分配内存


    如果变量是值类型,则该插槽[通常,但不总是]对象实例本身。但这并不是必然的。如果需要,可以(并且是)在堆上分配值类型。在这种情况下,变量的堆栈帧槽与值类型一样,是对堆上分配的实例的引用。

    Eric Lippert认为,假设的答案基本上是错误的——在大多数情况下。虽然你平时不应该在意。。。根据Eric的评论:)有趣的帖子:不幸的是,无论是谁创建了考试,似乎都不太了解这门学科——从他们问题的措辞和他们知道正确答案的信心来看(特别是在像C#这样极其复杂的语言中)。对于C#或类似的编程语言来说,一个不能区分变量和对象的讲师可能不是一个好的讲师。@DawnFreeze,正如目前所描述的,这是一个糟糕的问题,但这确实让我想知道,是否有额外的上下文没有在这里提出的考试问题。我认为,他们实际上是数据结构。。。堆栈可以展开或推/弹出(think:call stack),而堆是由指针访问的随机内存。@DVNRS我认为您可以给出您的评论,而不必对OP发表尖刻的评论。@DavidHaney抱歉,被自动完成咬了。。。更正了我的错误。@Lucmorin先生,他不是在侮辱OP,他是在批评OP引述问题的作者。@Lucmorin先生,我根本没有对OP发表讽刺性的评论。我在评论写这篇文章的考题的人。这并不是要讽刺,但我确实觉得这个问题写得很糟糕,这表明作者可能不是最好的讲师。(当然,每个人都会犯错。)这要看情况而定。捕获的本地存储在堆上。即使它们在概念上存储在堆栈中,从IL代码的角度来看,运行时可能最终只会将值存储在寄存器中,而永远不需要将其存储在内存中。然后再加上装箱和拆箱,这真是一团混乱的乐趣。:)@DavidHaney装箱对变量的内存存储位置没有影响。它可能对类型的给定实例的存储位置产生影响,可能是该变量的值,也可能不是该变量包含的引用,这不是问题所在。@DavidHaney好吧,它可能不在堆栈上,但如果不是,那是因为变量已关闭,或者在迭代器块中,等等。变量是装箱值类型、引用类型或值类型这一事实对该变量的内存存储位置没有影响,只影响变量“表示”的对象的存储位置。如果变量是值类型,则“插槽”始终是对象本身。这就是值类型的要点。它的定义是,该类型的变量始终包含实际对象,而对于引用类型,该类型的变量始终包含对存储在“别处”的对象的引用。值类型的变量是否存储在堆栈、堆或其他位置完全是另一回事,并且可以完全不同,但无论为该变量分配的“槽”在哪里,也就是存储对象值的确切位置,否则它就不是值类型。此外,“堆栈和堆”也不完全正确。除了这两个选项之外,还有其他选项,例如要注册的变量。