On Friday, 19 October 2018 at 02:04:37 UTC, Samir wrote:

I would have thought that since this is a dynamic array, I don't need to pre-assign its length.

Thanks


Just to expand on the previous answers, a dynamic array declaration with no initializer is an empty array:

int[] arr;
assert(arr.length == 0);

No memory has been allocated to store any elements. Appending elements will allocate memory. In fact, the runtime will allocate more than needed so that it doesn't have to allocate on each append.

arr ~= 1;
assert(arr.length == 1);
writeln(arr.capacity);

When the capacity is 0, the next append will trigger another allocation. The reserve function can be used to allocate enough memory for a number of elements, but the array will still be empty:

int[] arr;
arr.reserve(100);
assert(arr.length == 0);
writeln(arr.capacity);

Now 100+ elements can be appended without triggering an allocation.

Setting the length directly as Ali's example does means that not only is the required memory allocated, but also that the array is not empty.

int[] arr;
arr.length = 100;
assert(arr.length == 100);
writeln(arr.capacity);

And now the array can elements can be written to directly via the index operator, and a pointer to each element can be referenced as it is in the call to readf.

Note that it's still possible to write elements directly to a dynamic array without the append operator after memory has been reserved, but it completely bypasses the runtime.

void main() {
    int[] myArray;

    myArray.reserve(10);
    foreach(i; 0 .. 10) {
        *(myArray.ptr + i) = i;
    }

    assert(myArray == []);
    assert(myArray.length == 0);

    foreach(i; 0 .. 10) {
        writeln(*(myArray.ptr + i));
    }
}

This is essentially treating myArray.ptr as a C array, with no bounds checking and no automatic memory management. Here be dragons.

Reply via email to