How do you remove/insert elements in a dynamic array without allocating?
Malte Skarupke
malteskarupke at web.de
Mon Nov 5 18:28:09 PST 2012
On Tuesday, 6 November 2012 at 01:25:39 UTC, Jonathan M Davis
wrote:
> 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
Thanks, that explains it well. I must admit that I didn't fully
understand slices before. I've read the linked article and am
baffled that this is seen as acceptable behavior. I will most
certainly never use dynamic arrays or slices again for anything
that needs to grow or shrink dynamically.
More information about the Digitalmars-d
mailing list