How do you remove/insert elements in a dynamic array without allocating?

Jonathan M Davis jmdavisProg at gmx.com
Mon Nov 5 17:25:26 PST 2012


On Tuesday, November 06, 2012 02:11:06 Malte Skarupke wrote:
> Following code:
> 
> void main()
> {
> import core.memory;
> GC.disable();
> scope(exit) GC.enable();
> 
> int[] a = [1, 2, 3, 4, 5];
> foreach(i; 0 .. 1000000000)
> {
> --a.length;
> a ~= i;
> }
> }
> 
> That loop will keep on allocating in every iteration until your
> memory is full.
> 
> Is there a way to do something similar to this without
> allocating? I have also tried slicing:
> a = a[0 .. $ - 1]; // instead of (--a.length;)

There's no real difference between those two.

> But neither one works.
> 
> How do you work with the dynamic array without having to rely on
> the GC all the time? I want something similar to the stl vector,
> which only re-allocates once your array grows past a certain
> size, not on every append.

Arrays do work that way. They have capacity, and they have reserve. They only 
append when they don't have enough memory or they're not the last slice in the 
block. The problem is that if you remove elements, the runtime doesn't know if 
there's another slice pointing to the element which was just removed, so it 
has to assume that that there is, and it'll be forced to reallocate when 
appending.

If you _know_ that there are no slices of anything beyond the end of the 
array, then you can call assumeSafeAppend on the array, and then the runtime 
will mark it as the last slice in the block, and appending won't reallocate 
unless it actually runs out of space in the block (or you end up removing 
another element without calling assumeSafeAppend or you end up with a slice 
which contains elements beyond the end of that array - e.g. if you slice the 
array and then append to the slice). So, in this particular case, 
assumeSafeAppend would solve your problem. Whether it works in your program in 
general depends on what your program is doing. And if you want to make sure
that the array has enough space before appending to it a bunch, then you can
use reserve. However, if you're specifically building an array, you should
probably look at std.array.Appender. Don't remove elements from that though.
It's just for making appending more efficient, not for being used once the
array has been fully constructed.

If you haven't read it yet, I'd strongly advise reading this article on arrays 
in D:

http://dlang.org/d-array-article.html

- Jonathan M Davis


More information about the Digitalmars-d mailing list