我正在阅读有关Dispose模式的内容,并了解memory is allocated的方式。以下是http://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-memory/的引用。
内存分配
....
....
此规则的唯一例外是属于引用类型的值类型 - 例如,User类的Id属性与User类本身的实例一起出现在堆上。
这里也提到了有关Stack Overflow的问题。 memory allocation for value type inside reference type in .net
我的理解是,所有值类型无论它们在何处声明都会进入堆栈。现在这看起来不错了。在下面的代码中,i
将继续存在;根据链接不在堆栈上。这是因为MyClass
是引用类型,它将与堆及其所有值类型一起发送。
class MyClass()
{
int i = 5;
}
好的,所以只有那些不是类的一部分的值类型转到堆栈内存然后。对?但是,几乎所有像C#这样的Dot Net语言都是在课堂上。究竟是什么去堆栈内存?
这个answer解释了堆积的值类型。
如果是这种情况,堆栈内存中几乎没有甚至几乎没有。
我怀疑我误解了什么。
如果几乎所有数据都进入堆内存,我不明白堆栈内存的重要性/作用。
请解释。
以下两篇文章以简单的方式解释了很多关于内存管理的内容。
答案 0 :(得分:9)
不要将其视为“堆叠”和“堆积”。可以将其视为短期记忆和长期记忆。现在,很容易知道堆栈上发生了什么以及堆上发生了什么。 变量的生命周期是否长于当前方法的激活?如果是,那么它不是短暂的,而且必须在堆上。如果是,则可以进入堆栈。
例如:
class C {
void M() {
string s = Whatever();
Something(s);
}
}
本地变量s
可以用于短期池,因为它的持续时间不会超过方法的激活时间。
现在,你可能会说等一下,string是一个引用类型,所以它肯定会在堆上。不,它没有。 字符串在堆上,但变量不包含字符串。字符串是引用类型,因此变量包含引用,引用可以在堆栈中。 引用的东西在堆上,但引用本身是一个值,它可以放在堆栈上。
所以不要以为任何事物的类型都决定了它的存储位置。这种类型无关紧要。值类型或引用类型的变量如果是短期的,则可以在短期池中进行,如果不是,则必须在长期池中进行。
现在呢
class C {
void M() {
int i = Whatever();
X(() => i)
}
}
现在我可以上堆吗?不,X
可以存储传入的委托的副本,该委托需要知道i
的值,因此该变量需要比方法M
的激活更长时间,所以i
继续长期存在。 i
在这里堆。
同样,它是一个int的事实完全无关紧要。它是一个变量,它存在很长时间,因此它会堆积。
类的字段或数组的元素怎么样?那些是变数。只要类实例或数组实例存在,它们就会存在,因此它们的生命周期是不可预测的,因此它们会长期存在。
为什么我们有短期游泳池和长期游泳池?因为与长期池的垃圾收集器相比,短期池的垃圾收集器非常快速且便宜。因此,我们希望能够在可能的情况下在短期池中生成变量 - 即生命周期短。