Fast temporary dynamic arrays? (And slicing of them)

Jonathan M Davis jmdavisprog at gmail.com
Sun Sep 5 19:55:01 PDT 2010


On Sunday 05 September 2010 18:02:29 Tom Kazimiers wrote:
> Hi all,
> 
> so I have started to look at D and dug through the documentation, but
> could not get a good answer on the following:
> 
> How can I have a (temporary) dynamic array on stack and make references
> to it (no copying)? I successively put integers in an array (but don't
> know how much there will be in advance) with an appender!(int[]) and get
> the date out with appender.data(). Later on I pass the result to a
> method as an "in int[]" parameter. Is that already a reference or will
> it be copied? Are there better methods to accomplish this? The method
> receiving such an array will not modifiy contents of the array, but only
> read from it.

Static arrays are value types, but dynamic arrays are reference types.

void main()
{
    int[] a = new int[](3);
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;

    int[] b = a; //b now refers to a
    assert(a == b);
    assert(a is b);
    assert(a.length == b.length);
    assert(a[0] == b[0]);
    assert(a[1] == b[1]);
    assert(a[2] == b[2]);

    b = new int[](2); //b now refers to a different array
    b[0] = 5;
    b[1] = 6;
    assert(a != b);
    assert(a !is b);
    assert(a.length != b.length);
    assert(a[0] != b[0]);
    assert(a[1] != b[1]);

    b = a[]; //b now refers to a full slice of a
    assert(a == b);
    assert(a is b);
    assert(a.length == b.length);
    assert(a[0] == b[0]);
    assert(a[1] == b[1]);
    assert(a[2] == b[2]);

    b = a[1..$]; //b now refers to a partial slice of a
    assert(a != b);
    assert(a !is b);
    assert(a.length != b.length);
    assert(a[1] == b[0]);
    assert(a[2] == b[1]);
}



No array copying takes place anywhere in that program. If you want to copy an array, you'd do one of the following

void main()
{
    int[] a = new int[](3);
    a[0] = 1;
    a[1] = 2;
    a[2] = 3;

    int[] b = new int[](3);
    b[] = a[]; //b is now a copy of a (the contents of a were copied to b)
    assert(a == b);
    assert(a !is b);
    assert(a.length == b.length);
    assert(a[0] == b[0]);
    assert(a[1] == b[1]);
    assert(a[2] == b[2]);

    int[] c = a.dup; //c is now a copy of a (a new copy of a was created)
    assert(a == c);
    assert(a !is c);
    assert(a.length == c.length);
    assert(a[0] == c[0]);
    assert(a[1] == c[1]);
    assert(a[2] == c[2]);

    immutable(int[]) d = a.idup; //d is now an immutable copy of a (a new copy of a was created)
    assert(a == d);
    assert(a !is d);
    assert(a.length == d.length);
    assert(a[0] == d[0]);
    assert(a[1] == d[1]);
    assert(a[2] == d[2]);
}


Passing dynamic arrays to functions passes the reference. So, as long as you don't alter the reference directly or resize the array in any way which would cause reallocation, the reference in the called function will refer to the array which was passed in and any alterations to its elements will alter the original. However, if you set the local reference to something else, or if you resize the array in a manner which would cause a reallocation, then the local reference would refer to a different chunk of memory, and any alteration to its elements would not affect the original.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list