![]() |
1
38
Eric Lippert对此进行了讨论 here 有时 是,但不是:
当他们 可以 存储在堆栈上这是一种方便的建模其生命周期的方法,但事实并非如此 必修的 将它们存储在堆栈上。您可以编写一个编译器+CLI,它不会 有 例如,堆栈。 |
![]() |
2
16
好吧,首先,它只是偶尔发生。以下内容不会出现在堆栈上:
第二,如果可能的话,这是因为它是有效的。基本上在CLR内存模型中,相对于堆上的释放,堆栈上的释放非常便宜。对于值类型的局部变量,您可以确保除了局部变量之外没有其他人会引用内存,这样您就可以不用使用堆栈而不用堆了。有关详细信息,请参阅 Eric Lippert 最后,值类型的特殊之处在于它们具有值类型语义(按值复制),而不是它们有时在堆栈上被分配。C#规范中没有要求编译器发出指令来分配堆栈上的值类型。C#规范要求值类型具有值类型语义。 |
![]() |
3
5
正如@Akash所指出的,它主要与内存有关。在CLR的设计过程中,有人指出(我的猜测来自Java的经验),将小的原始类型表示为具有垃圾收集器句柄的对象会导致大量跟踪开销。所以设计师想要一个“轻量级”的对象,而不需要跟踪。 CLI规范中没有关于要堆栈分配的原语的具体要求;这是机器上实现的工件。重要的一点是运行时知道实例的位置是由于构造了定义良好的内存模式(称为帧),而不是在GC的分配对象索引中。在x86(和类似的)机器上,这可以通过使用堆栈高效地完成。 |
![]() |
4
2
此外,ValueType可以是局部变量或引用类型内的字段。因此,值类型并不总是存储在堆栈上。更有用的说法是:referencetypes是 所以不要过于关注堆栈,它是一个实现细节。了解 value- and reference-types |
![]() |
5
1
堆栈操作或堆操作,它们都将与访问位于两个不同位置的内存地址相同。 值类型是small、int、byte等,它们的大小很小,并且在数学计算中经常被引用。由于它们的大小非常小,最多4到16个字节(为了获得最佳性能,在值类型中不应使用超过16个字节),因此在堆上分配如此小的空间以及释放、垃圾收集等都将非常昂贵。 我们输入的每个方法,平均来说,我们定义10个本地值类型在内部使用它,这在堆上作为引用类型将非常昂贵。 堆栈可以轻松地增长和收缩(不是堆栈大小,而是用于当前方法的堆栈部分!!)由于ValueType只是作为堆栈指针的偏移量来处理,它们的分配和解除分配很容易,因为它在stackpointer上简单地按所使用的所有ValueType的总大小递增和递减。 在引用类型中,每个引用对象都有自己的分配和大小调整,加上CLR必须维护对象表,该表类似于内存中实际指针的索引,以避免缓冲区溢出。所以,您使用的一个对象(引用类型)实际上有两个存储、CLR引用表中的一个索引项和实际内存空间。这就是为什么在堆栈上存储值类型既简单又快速。 |
![]() |
6
0
|
![]() |
dallin · 数组中的逗号运算符是否有名称? 11 年前 |