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

wjoe invalid at example.com
Thu Jul 30 23:42:36 UTC 2020


On Thursday, 30 July 2020 at 16:33:22 UTC, Ali Çehreli wrote:
> On 7/30/20 8:58 AM, wjoe wrote:
>
>>          b.reserve(n);
>>          b.length = n;
>
> There may be something that I don't know but I think assigning 
> to the .length property alone should be the same as reserving 
> and then assigning.
>
> reserve is supposed to make sure no memory will be allocated as 
> elements are added.

So whichever instruction is redundant depends on whether I want 
an array of length n, or an empty array that can grow to at least 
n elements without reallocation.

> This article is considered a must-read for understanding what 
> is going on behind the scenes:
>
>   https://dlang.org/articles/d-array-article.html
>
> I tried to introduce the concept of slices "sharing elements" 
> as well as how .capacity is used to determine whether sharing 
> will be terminated, here:
>
>   http://ddili.org/ders/d.en/slices.html#ix_slices..capacity
>
> Ali

These resources are great. Thanks.



On Thursday, 30 July 2020 at 16:55:35 UTC, Steven Schveighoffer 
wrote:
> On 7/30/20 11:58 AM, wjoe wrote:
>> 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.

So .capacity can't be assigned a value like length to reserve the 
RAM ?

>> 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].

So this is a case of sharing being terminated ?

> 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).

This array is a private array of pointers to released structs - 
technically a stack.
Every time a new element is requested, the most recently released 
element would be taken off the stack and be set to the new data 
until the stack was exhausted.
Expired structs are put back into (appended to) the array for 
reuse.
When the length of the array == 0, upon releasing a struct, this 
array is reallocated which isn't supposed to happen. It should 
just grow like it did with length > 1.
assumeSafeAppend should accomplish that :)

>> 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.
>
> -Steve

I could swear just a few weeks ago there was someone asking how 
to tell if an array was null or of length 0 and an answer was 
that it's the same and can't be distinguished so I assumed that 
assigning a slice of 0 length is the same as setting the array to 
null because the result is the same as a 0 length array.
Thanks for the explanations and corrections.



bachmeier, a picture tells more than a thousand words. Your 
illustration is very comprehensive. Thanks :)


Thank you everyone, your input is very much appreciated :)


More information about the Digitalmars-d-learn mailing list