On Sat, 10 Apr 2010 18:17:12 -0400, bearophile <bearophileh...@lycos.com> wrote:

This can help confuse your mind a bit:

import std.stdio: writeln;
void main() {
    {
        int[] arr = [0, 1, 2, 3, 4, 5, 6].dup;
        int[] slice = arr[2 .. 4];
writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2 3 4 5 6 | 2 3
        slice ~= 10; slice ~= 20;
writeln("arr.capacity, slice.capacity: ", arr.capacity, " ", slice.capacity); // arr.capacity, slice.capacity: 7 7 writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2 3 4 5 6 | 2 3 10 20
    }

    {
        int[] arr = [0, 1, 2, 3, 4, 5, 6].dup;
        int[] slice = arr[2 .. 4];
writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2 3 4 5 6 | 2 3

        slice.assumeSafeAppend;
        slice ~= 10; slice ~= 20; // causes stomping
writeln("arr.capacity, slice.capacity: ", arr.capacity, " ", slice.capacity); // arr.capacity, slice.capacity: 0 5 writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2 3 10 20 6 | 2 3 10 20
        slice ~= 30; slice ~= 40;
writeln("arr.capacity, slice.capacity: ", arr.capacity, " ", slice.capacity); // arr.capacity, slice.capacity: 7 7 writeln("arr, slice: ", arr, " | ", slice); // arr, slice: 0 1 2 3 10 20 30 | 2 3 10 20 30 40
    }
}


The slice.capacity = 7 in the first case is just a coincidence, it's the result of the overallocation.

Yes, to allocate an array of 4 integers, you need 16 bytes, but there needs to be a padding byte to prevent cross-block pointer problems, so it uses a 32-byte block. The 32-byte block also needs a padding byte, so really you can only put in 7 elements, not 8.

But I don't know why arr.capacity is zero and then seven in the second and third case.

0 means if you append to the array, it will reallocate. It will return 0 for stack-allocated arrays also. This makes sense since the slice has taken over the "allocated" length of the block. Essentially, capacity indicates how many elements can be appended. The function gives up and returns 0 if it determines the array does not end at the allocated part of a block. Technically, I could return the length of the array, but I'm not sure whether that is as useful.

For fun, add one more element to slice, and the arr will now have a valid capacity :)

FYI, using arr after assuming safe append on the slice is undefined.

-Steve

Reply via email to