我认为 ints1 是用新关键字初始化的new List<int>()
它成为引用类型
这个假设是不正确的。您也可以在值类型上使用“new”关键字!
int x = new int();
使用“new”并不会使任何东西成为引用类型。您可以将“new”与引用类型或值类型一起使用。 “新”所指的是将分配存储空间并调用构造函数.
在值类型上使用“new”的情况下,分配的存储是临时存储。对该临时存储的引用将传递给构造函数,然后将现在初始化的结果复制到其最终目的地(如果有)。 (“new”通常与赋值一起使用,但不一定如此。)
在引用类型的情况下,存储被分配两次:长期存储被分配给instance和短期存储分配给对实例长期存储的引用。该引用被传递给构造函数,该构造函数初始化长期存储。然后,将该引用从短期存储复制到其最终目的地(如果有)。
是什么使得List<int>
引用类型是List<T>
被声明为一个类。
值 1,2,3 存储在内存中的什么位置(它们存储在堆栈中还是堆中)?
我们努力打造一个内存管理器,让您不必关心内容存储在哪里。值存储在短期内存池(实现为堆栈或寄存器)或长期内存池(实现为垃圾收集堆)中。存储空间的分配取决于已知寿命的值。如果已知该值是短期的,则其存储空间将分配在短期池上。如果值为not已知其寿命较短,则必须将其分配到长期池中。
列表中的1、2、3可以永远存在;我们不知道该列表是否会比当前激活帧更长久。因此,存储 1、2、3 的内存被分配在长期池上。
不要相信“值类型总是在堆栈上分配”的谎言。显然这是不可能的,因为包含数字的类或数组无法在当前堆栈帧中生存!值类型在对其已知生命周期有意义的池上进行分配。
List<int>
可以在运行时将其大小缩放到任意大小,这与int[]
正确的。看看如何做是有教育意义的List<T>
这样做。它只是分配一个比它需要的更大的 T 数组。如果它发现猜测太小,它会分配一个更大的新数组,并将旧数组内容复制到新数组中。 AList<T>
只是一堆数组副本的方便包装!
如果值 1,2,3 存储在堆栈中,并且将新项目 4 添加到列表中,那么它将不会连续到前三个。
正确的。这就是为什么值 1、2、3 的存储空间没有在堆栈上分配的原因之一。存储实际上是分配在堆上的数组。
那么列表如何知道第 4 项的内存位置呢?
该列表分配一个数组,即too big。当您添加新项目时,它会将其粘贴到太大数组中未使用的空间中。当数组空间不足时,它会分配一个新数组。