在.NET中,连续存储内存的误解?

10

http://msdn.microsoft.com/zh-cn/library/ms379570(v=vs.80).aspx

我知道在 .net 中,Arrays 以连续的方式存储在内存中。

我也知道 List<..> 不是这样的( 好吧...不是所有类型的列表...请看我的第二个问题)

接下来有两个问题:


  1. 我知道当一个列表中插入了4、8、16...个项后,列表会在内存中重新分配。

    我还知道我可以在构造函数中发送给它 Capacity ,以便让他知道我将创建它的大小(以减少重新分配)。

    问题是为什么?它并没有按连续方式存储自己,那它为什么要关心重新分配呢?(它不需要找到空闲和连续的内存单元)

  2. 为什么由结构体组成的列表会被分配在连续的内存中,而由类组成的列表却不是?


错过了那个,抱歉 Oded。 - MethodMan
2个回答

25
List<T> 存储内存是连续的。它在内部使用一个数组进行存储。当达到容量时,会分配一个新的数组并复制内存。
对于类或结构的 List<T> 实例来说,这是正确的。然而,当 T 是引用类型(类)时,你存储的是一组连续的引用。由于列表中可以包含指向同一类实例的 100 个引用,因此类实例不能是连续的。
因此,为了回答您的具体问题:

The question is why ? he Doesn NOT store itself contiguously , so why does he care about re- allocating himself ?

它确实将项存储在连续位置,这就是为什么需要重新分配的原因。

why Does List with structs is allocated in contiguous memory, unlike a List of classes?

两者都是连续存储的,但在第二种情况下(类),你存储的是指向类实例的引用列表。

如果我创建一个只有1个项目的列表,而且它没有连续的位置来存储第二个项目,那么它是否仍会重新分配内存? - Royi Namir
@RoyiNamir 当你添加一个超出当前容量的项时,列表将立即重新分配空间。如果您使用容量为1创建列表,则添加第二个项将导致重新分配。对于类来说,这并不是可怕的,因为你只需要重新分配和复制对象引用,而不是对象实例本身。 - Reed Copsey
有人能解释一下为什么需要使用List<>来存储其数据连续吗?我知道它需要比集合更高级的随机访问要求,但是你不能在非连续内存中实现随机访问,而且有多个块吗?这样,如果我有一个需要100MB内存的列表,它可以分配5MB的块或其他可能更有效的操作系统。我可能漏掉了什么。 - zumalifeguard
1
@zumalifeguard,这并不是一个“要求”,而只是针对该特定集合所做的决定。有些人已经为.NET实现了块式集合。连续数据确实可以允许更快(特别是在内联之后)的读取,但代价是更昂贵的创建/添加。它还为一旦构建就进行读取提供了更好的缓存一致性。 - Reed Copsey
@zumalifeguard 我认为C5有一个,但现在找不到了 - http://fsprojects.github.io/FSharpx.Collections/reference/fsharpx-collections-persistentvector-1.html 是一个(虽然是用F#编写的) - Reed Copsey
显示剩余2条评论

0

1) 所有对象的引用仍然被连续存储。

2) 类列表仍必须让对象像普通对象一样存储。它们不能被强制存储到连续的数组中,但是对它们的引用可以。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接