Arrays passed by almost reference?
Travis Boucher
boucher.travis at gmail.com
Thu Nov 5 06:28:25 PST 2009
dsimcha wrote:
> == Quote from Ali Cehreli (acehreli at yahoo.com)'s article
>> I haven't started reading Andrei's chapter on arrays yet. I hope I won't find
> out that the following behavior is expected. :)
>> import std.cstream;
>> void modify(int[] a)
>> {
>> a[0] = 1;
>> a ~= 2;
>> dout.writefln("During: ", a);
>> }
>> void main()
>> {
>> int[] a = [ 0 ];
>> dout.writefln("Before: ", a);
>> modify(a);
>> dout.writefln("After : ", a);
>> }
>> The output with dmd 2.035 is
>> Before: [0]
>> During: [1,2]
>> After : [1]
>> I don't understand arrays. :D
>> Ali
>
> This is one of those areas where the low-level details of how arrays are
> implemented arrays leak out. This is unfortunate, but in a close-to-the-metal
> language it's sometimes a necessary evil.
>
> (Dynamic) Arrays are structs that consist of a pointer to the first element and a
> length. Essentially, the memory being pointed to by the array is passed by
> reference, but the pointer to the memory and the length of the array are passed by
> value. While this may seem ridiculous at first, it's a tradeoff that allows for
> the extremely convenient slicing syntax we have to be implemented efficiently.
>
> When you do the a[0] = 1, what you're really doing is:
>
> *(a.ptr) = 1;
>
> When you do the a ~= 2, what you're really doing is:
>
> // Make sure the block of memory pointed to by a.ptr
> // has enough capacity to be appended to.
> a.length += 1;
> *(a.ptr + 1) = 2;
>
> Realistically, the only way to understand D arrays and use them effectively is to
> understand the basics of how they work under the hood. If you try to memorize a
> bunch of abstract rules, it will seem absurdly confusing.
main.a starts as:
struct {
int length = 1;
int *data = 0x12345; // some address pointing to [ 0 ]
}
inside of modify, a is:
struct { // different then main.a
int length = 2;
int *data = 0x12345; // same as main.a data [ 1, 2]
}
back in main:
struct { // same as original main.a
int length = 1;
int *data = 0x12345; // hasn't changed address, but data has to [ 1 ]
}
To get the expected results, pass a as a reference:
void modify(ref int[] a);
More information about the Digitalmars-d
mailing list