dynamic array .length vs .reserve - what's the difference?

Steven Schveighoffer schveiguy at gmail.com
Thu Jul 30 16:55:35 UTC 2020

On 7/30/20 11:58 AM, wjoe wrote:
> I just stumbled upon code like this:
> struct Foo(T)
> {
>      T[] b;
>      this(int n)
>      {
>          b.reserve(n);
>          b.length = n;
>      }
> }
> ..reserve looks redundant.

It is, in this case. Reserve will extend the allocated length to n, but 
not adjust the slice, and setting the length will adjust the slice and 
consume that data from the block. Just setting length has the same effect.

> The docs are explaining .length nicely, however lack any specifics about 
> reserve.
> Changing the length of an array may relocate and copy. New items are 
> initialized with T.init - is that true for both length and reserve ?

reserve preallocates data for use in appending, but does not alter the 
length of the specified array.

It's like saying, "I'm going to append enough elements to this array so 
the total length is N." It's very much tied to appending.

Note that reserve may do nothing, if there is already at least N 
elements available.

> Also there's .capacity - is that equivalent to reserve ?

Capacity tells you how many total elements the current reserved space 
can hold. If the array is not appendable, then this returns 0.

> Another curiosity I noticed is that the docs say that the runtime tries 
> to resize in place, however:
> b = b[0..$-1]; if length==1 seems to collect the memory at once because 
> if it's immediately followed by b.length = 1; or b ~= someT; b.ptr 
> points to a new address.
> Why ?

Because you would be overwriting the data already in the array.

For example:

auto a = b;
b = b[0 .. $-1];
b ~= someT;

If that last line is done in-place, then it overwrites a[$-1].

If you know that it's OK to do this, then you should call 
assumeSafeAppend on the array (which will adjust the "used" space down 
to the current array).

> I know that b=b[0..0]; is equivalent to b = null;

No, if slicing b to b[0 .. 0], b.ptr does not change. b = null sets the 
pointer to null. In the former case, if you called assumeSafeAppend on 
it, then it could append in-place at that point. With the null pointer, 
it would reallocate.


More information about the Digitalmars-d-learn mailing list