从列表中获取数组而不进行堆分配

Posted

技术标签:

【中文标题】从列表中获取数组而不进行堆分配【英文标题】:Get array from list without heap allocation 【发布时间】:2016-03-30 15:16:33 【问题描述】:

我有一个列表,我想将它的数组分配给一个属性。

public void BuildMesh(List<Vector3> list)
    mesh.vertices=list.ToArray();

现在的问题:

该项目是游戏,在垃圾收集方面非常困难,因此 ToArray() 的默认实现不是一个选项,因为它会在列表的内部数组旁边创建一个新数组。 网格对象来自封闭源 API,顶点属性是 Vector3[],因此无法为其分配指针。

我是否有任何选项来阻止堆分配?

编辑:这不是重复的

不能使用IList&lt;Vector3&gt;。网格来自闭源 API,需要 Vector3[],因此我无法将 IList&lt;Vector3&gt; 分配给它。

【问题讨论】:

List<T> to T[] without copying的可能重复 @VadimMartynov 这是另一个问题。网格来自封闭源 API,需要 Vector3[],因此我无法将 IList 分配给它。 如果您有固定大小的对象,请不要丢弃该对象。相反,只需将对象标记为未使用。在程序开始时创建一个固定的对象数组。然后标记已使用或未使用的对象,而不是创建和处置该对象。不需要垃圾收集。 List 中的内部数组与您看到的实际项目大小不同。你也许可以通过反射来做到这一点,但它本身的反射比简单的 ToArray 会造成很多混乱。例如,如果您有 80 个项目,如果您直接获取内部数组,您将获得大小为 128 的数组。如果列表太大,也许反射会有所帮助。你必须自己测试一下。 @M.kazemAkhgary 这就是重点。由于您提到它的确切原因,不能使用内部数组。在您描述的情况下,内部数组是 128,但我需要一个包含 80 个成员的数组。 【参考方案1】:

我认为您正在使用 Unity。如果我是对的,请尝试接受List&lt;Vector3&gt;mesh.SetVertices(list)

【讨论】:

是的,它有效。我也很想找到该问题的一般解决方案。 我认为这是不可能的,因为 List 的内部数组可能比它的 Count 大。如果经常使用特定数量的顶点,比如一直使用 64 个顶点,那么您可以尝试重用该数组以防止进一步的堆分配。 Setvertices 与零 GC 分配完美配合。所以我的问题基本上解决了这个问题,我+1了你的答案。该问题作为一般 C# 问题也有效。如果我们在 API 中遇到非统一的情况怎么办? 我认为这与 API 设计有关。如果 API 设计为通常与可重复使用的固定大小缓冲区一起使用,那么数组是好的,例如 System.IO.Stream API。否则,API 的设计就很糟糕。

以上是关于从列表中获取数组而不进行堆分配的主要内容,如果未能解决你的问题,请参考以下文章

内存管理相关API列表

内存堆问题 C++,动态分配多维数组

4-数组指针与字符串1.4-动态内存分配

gcc警告分配使指针从整数而不进行强制转换[重复]

java分配内存空间

获取动态分配的数组大小