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