因为 Value 类型变量在Stack中分配内存,而 Reference 类型在Heap中分配内存。那么,当一个值类型变量(例如int i = 4;)在引用类型(例如类)中声明时,内存是如何分配的。NET中值类型和引用类型以及引用类型范围内的值类型的整体内存分配是如何工作的。请解释它或提供有关的任何链接。
int i = 4;
gr8qqesn1#
值类型变量在堆栈上分配内存,而引用类型在堆中分配内存。不,那种说法是完全错误的。很多人都相信,但正如你所发现的,它显然是错误的。当值类型变量int i = 4;被声明为引用类型的字段时,内存是如何分配的?显然你知道为什么你的第一条语句是完全错误的。类的整型字段不能在堆栈上分配,因为对象的生存时间可能比堆栈帧长。要理解到底发生了什么,首先你必须意识到有三种事情:
接下来您必须了解的是,存储有两种:长期存储和临时存储。长期存储通常被称为“堆”,但我更喜欢简单地将其视为长期存储。临时存储通常被称为“堆栈”,但这也会引起误解,因为当然可能存在多个堆栈,可能存在存储在寄存器中的临时数据,等等。引用类型的一个示例占用了长期存储器中的内存。(有时可以确定引用类型的一个示例是短期的,并将其放入临时存储器中,但实际上我们不做这种优化。)
变量的存储位置取决于变量的生存期。如果变量是一个已知生存期短的局部变量,则从临时存储池分配。如果变量已知生存期长(因为,比方说,它是闭包的外部变量),则从长期存储池分配。如果变量是一个类的字段,我们已经知道它的存储来自长期池;如果变量是一个值类型的字段,那么这个值类型驻留在某个地方;字段占据相同的存储器。如果变量是数组元素,则从长期存储池中分配;数组是引用类型的示例。正确理解的关键是不要再相信变量是引用类型还是值类型会影响存储空间分配的神话,这不是真的,从来都不是真的,甚至没有任何意义。影响变量存储位置的唯一因素是变量的生存时间.短期变量从临时池(堆栈或寄存器)中分配,长期变量从长期存储池(堆)中分配。
6ju8rftf2#
这就是为什么Eric Lippert提醒我们当一个值类型的示例是引用类型的成员时,它与父对象沿着存储在托管堆中。这是一个很好的问题,你应该理解,只是在大多数情况下不应该驱动你的设计。structs应该是小而简单的数据类型,创建和传递起来相对便宜。引用类型是复杂类型,只需要一个引用的副本就可以传递给方法,但是由于是在堆上分配的,当然也会带来一些负担。下面是一个很好的follow up post,它涉及到堆栈和堆分配的含义。有大量的参考资料解释了值类型与引用类型的性能影响。你应该学习所有关于它的知识,并且也要明白,大多数时候,这是一个“语义”决定,而不是一个性能决定。
structs
lyfkaqu13#
那么当一个值类型变量(例如int i =4;)在引用类型中声明(例如在类中)。如果对象位于heap上,则意味着它的所有成员变量都位于那里。
utugiqy64#
这是一个不错的article。顺便说一句:并不是所有的堆栈都有一个值--它可能以堆结束。
4条答案
按热度按时间gr8qqesn1#
值类型变量在堆栈上分配内存,而引用类型在堆中分配内存。
不,那种说法是完全错误的。很多人都相信,但正如你所发现的,它显然是错误的。
当值类型变量
int i = 4;
被声明为引用类型的字段时,内存是如何分配的?显然你知道为什么你的第一条语句是完全错误的。类的整型字段不能在堆栈上分配,因为对象的生存时间可能比堆栈帧长。
要理解到底发生了什么,首先你必须意识到有三种事情:
reference和reference类型的示例是完全不同的,就像包含我的地址的一张纸和我实际的房子是完全不同的。
接下来您必须了解的是,存储有两种:长期存储和临时存储。长期存储通常被称为“堆”,但我更喜欢简单地将其视为长期存储。临时存储通常被称为“堆栈”,但这也会引起误解,因为当然可能存在多个堆栈,可能存在存储在寄存器中的临时数据,等等。
引用类型的一个示例占用了长期存储器中的内存。(有时可以确定引用类型的一个示例是短期的,并将其放入临时存储器中,但实际上我们不做这种优化。)
变量的存储位置取决于变量的生存期。如果变量是一个已知生存期短的局部变量,则从临时存储池分配。如果变量已知生存期长(因为,比方说,它是闭包的外部变量),则从长期存储池分配。
如果变量是一个类的字段,我们已经知道它的存储来自长期池;如果变量是一个值类型的字段,那么这个值类型驻留在某个地方;字段占据相同的存储器。
如果变量是数组元素,则从长期存储池中分配;数组是引用类型的示例。
正确理解的关键是不要再相信变量是引用类型还是值类型会影响存储空间分配的神话,这不是真的,从来都不是真的,甚至没有任何意义。
影响变量存储位置的唯一因素是变量的生存时间.短期变量从临时池(堆栈或寄存器)中分配,长期变量从长期存储池(堆)中分配。
6ju8rftf2#
这就是为什么Eric Lippert提醒我们
当一个值类型的示例是引用类型的成员时,它与父对象沿着存储在托管堆中。这是一个很好的问题,你应该理解,只是在大多数情况下不应该驱动你的设计。
structs
应该是小而简单的数据类型,创建和传递起来相对便宜。引用类型是复杂类型,只需要一个引用的副本就可以传递给方法,但是由于是在堆上分配的,当然也会带来一些负担。下面是一个很好的follow up post,它涉及到堆栈和堆分配的含义。有大量的参考资料解释了值类型与引用类型的性能影响。你应该学习所有关于它的知识,并且也要明白,大多数时候,这是一个“语义”决定,而不是一个性能决定。
lyfkaqu13#
那么当一个值类型变量(例如int i =4;)在引用类型中声明(例如在类中)。
如果对象位于heap上,则意味着它的所有成员变量都位于那里。
utugiqy64#
这是一个不错的article。
顺便说一句:并不是所有的堆栈都有一个值--它可能以堆结束。