Thread overview
A question regarding Array capacity, length and slices
May 29, 2014
Sourav
May 29, 2014
Ali Çehreli
May 29, 2014
Sourav
May 29, 2014
Hello,

I am quite new to D and working my way through the D tutorials. While learning about slices and capacity I found that depending upon the initial number of elements in a slice (and hence its capacity) the behavior of the code changes. Consider this program:

<snip>
import std.stdio;

void main()
{
    int[] original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
    //int[] original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
    int[] duplicate = original[0..$-1];

    writefln("original = %s", original);
    writefln("duplicate = %s", duplicate);

    writefln("original(capacity = %s, length = %s)", original.capacity, original.length);
    writefln("duplicate(capacity = %s, length = %s)", duplicate.capacity, duplicate.length);

    original ~= 100;
    duplicate[2] = 200;

    writeln("\nAFTER\n");

    writefln("original = %s", original);
    writefln("duplicate = %s", duplicate);

    writefln("original(capacity = %s, length = %s)", original.capacity, original.length);
    writefln("duplicate(capacity = %s, length = %s)", duplicate.capacity, duplicate.length);
}

</snip>

The output of this program is:

original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
duplicate = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
original(capacity = 15, length = 14)
duplicate(capacity = 0, length = 13)

AFTER

original = [1, 2, 200, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 100]
duplicate = [1, 2, 200, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
original(capacity = 15, length = 15)
duplicate(capacity = 0, length = 13)

However, if the original slice in the comment is used instead of the first one:

<snip>
int[] original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
</snip>

the output changes to:

original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
duplicate = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
original(capacity = 15, length = 15)
duplicate(capacity = 0, length = 14)

AFTER

original = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 100]
duplicate = [1, 2, 200, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
original(capacity = 31, length = 16)
duplicate(capacity = 0, length = 14)

I understand that in the first case, capacity was one more than length and so there was space to allocate one more element. So the slice was not reallocated to a different space and original/duplicate referred to the same array (and both had third element updated to 200). But in the second case original's capacity was full and it was reallocated and hence update to duplicate was not reflected in original. But what looks strange to me is that the behavior totally depends upon how many elements were present initially in the array, which means, the capacity of a slice can actually introduces little surprises in the code! Is this expected behavior or am I entirely missing something here?

Thanks!
May 29, 2014
On 05/29/2014 12:37 AM, Sourav wrote:

> the behavior totally depends upon how many
> elements were present initially in the array, which means, the capacity
> of a slice can actually introduces little surprises in the code! Is this
> expected behavior or am I entirely missing something here?

It is by design. I tried to explain this behavior under the section "Making a slice longer may terminate sharing" here:

  http://ddili.org/ders/d.en/slices.html

The section "capacity to determine whether sharing will be terminated" shows a way to detect whether sharing will be terminated.

Steven Schveighoffer's array article goes into design and implementation details:

  http://dlang.org/d-array-article.html

Ali

May 29, 2014
Thanks! Just what I needed to understand. :-)

On Thursday, 29 May 2014 at 08:12:10 UTC, Ali Çehreli wrote:
> On 05/29/2014 12:37 AM, Sourav wrote:
>
> > the behavior totally depends upon how many
> > elements were present initially in the array, which means,
> the capacity
> > of a slice can actually introduces little surprises in the
> code! Is this
> > expected behavior or am I entirely missing something here?
>
> It is by design. I tried to explain this behavior under the section "Making a slice longer may terminate sharing" here:
>
>   http://ddili.org/ders/d.en/slices.html
>
> The section "capacity to determine whether sharing will be terminated" shows a way to detect whether sharing will be terminated.
>
> Steven Schveighoffer's array article goes into design and implementation details:
>
>   http://dlang.org/d-array-article.html
>
> Ali