www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - A question regarding Array capacity, length and slices

reply "Sourav" <soura.jagat gmail.com> writes:
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
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
parent "Sourav" <soura.jagat gmail.com> writes:
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
May 29 2014