2014-08-27 60 views
5

我必须完全傻,因为我无法完全理解这一点:如何在元素未被复制的情况下添加元素。D:在不复制的情况下向阵列添加元素

换句话说,让我们说,我想创造的东西的大名单:

int[] arr; 

while (...) { // 1,000,000 iterations 
    ... 
    arr ~= something; 
    ... 
} 

我不太明白什么时候~=将刚刚添加到阵列中,而当它会创建一个副本。为了澄清,我正在寻找像Java或C#中的ArrayList这样的语义,即一些抽象的容器,我可以将它们放入并在需要时会增长,但通常保持相同的“对象”(即,如果绕过等等)。

回答

9

它的工作原理几乎与ArrayList的工作方式相同,它具有capacity这是可以增长到要重新分配的元素的数量。然而,由于将数组传递给一个函数而不是使它成为相同的数组,事实很复杂。如果你只是使用一个局部变量而不把它分配给任何东西,那么在重新分配时应该不重要,除了效率。

,你应该读条是这样的:http://dlang.org/d-array-article.html

我认为它使用稍有不当用语,因为它指的是内存运行时管理为动态数组,而不是T[]块 - 这是该规范认为是一个动态数组,而内存块恰好是此刻数组支持的内容 - 但它很好地解释了D中数组如何工作的大量细节。所以,它应该很有启发性。

另外,如果您正在进行大量附加操作,您应该考虑使用std.array.Appender。例如

auto app = appender!(int[])(); 

while (...) { // 1,000,000 iterations 
    ... 
    app.put(something); 
    ... 
} 

int[] arr = app.data; 

它会使追加更高效。一般来说,如果你创建数组然后对它们进行操作,而不是稍后再添加它们,你可能会做得更好。显然,这并不适合所有的用例,但如果你这样做,那么你就不用担心一个切片是否仍然指向与另一个切片相同的内存 - 无论是这样的代码还是代码都不依赖于两个切片指向相同的内存。

另一种方法是使用std.container.Array这是一个完整的参考类型(而不是像D的动态数组那样的半参考类型)。当然,如果你想要传递一个数组,有多个片段都指向相同的内存,并继续追加它,你应该考虑使用Array来代替。

+0

所以总结一下,看看我是否明白:只要数组是一个局部变量,不会传递,或者是一个类成员,或者作为'ref'传递的,我可以把它当作一个'ArrayList '。对于批量追加使用'appender'。为了传递一个稍微修改过的大数组,使用'Array'。这或多或少是正确的? – 2014-08-28 12:29:56

+0

@AmirAbiri或多或少,是的。传递一个数组会导致数组指向相同的内存,但不相互引用,所以如果其中一个必须重新分配,那么它不会再引用与其他内存相同的内存。所以,如果你在传递之后没有追加,传递它就没问题,但如果你是这样的话,那么你需要通过'ref'传递它,或者使用另一个解决方案(比如'Array')。而'Appender'使追加效率更高,所以如果你通过大量的追加来构建一个数组(而不是仅追加几次),最好使用它。 – 2014-08-28 18:37:11

相关问题