Summary: Initialization syntax for dynamic arrays
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD

--- Comment #0 from 2011-02-16 16:23:03 PST ---
Fixed-sized arrays allow to specify an initialization value, or to not specify
one, or to leave the stack memory untouched, for special situations where
performance matters a lot:

// program #1
void main() {
    int[5] a2 = void;

    int[5] a1 = 1;

    int[5][5] m2 = void;

    int[5][5] m1 = 1;

Dynamic arrays don't allow to specify an initialization value (expecially after
the deprecation of 'typedef', that used to allow the definition of a new int
type with a different init value). DMD has no syntax to allocate an unitialized
array, and currently it is not able to avoid double initializations of dynamic
arrays, an example:

// program #2
void main() {
    auto a1 = new int[5];
    a1[] = 1;

Asm of program #2 (optimized built). __d_newarrayT performs a first
initialization to zero, __memset32 performs a second initialization:

__Dmain comdat
L0:     sub ESP,01Ch
        mov EAX,offset FLAT:_D11TypeInfo_Ai6__initZ
        push 5
        push EAX
        call near ptr __d_newarrayT
        mov 0Ch[ESP],EAX
        mov 010h[ESP],EDX
        push dword ptr 0Ch[ESP]
        push 1
        push EDX
        call near ptr __memset32
        add ESP,014h
        add ESP,01Ch
        xor EAX,EAX

So to translate the program #1 for dynamic arrays you need something like this
(I am not sure this is fully correct. GC.disable are used because m1/m2 contain
uninitialized pointers):

// program #3
import core.memory: GC;

void main() {
    uint ba1 = GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE;
    int n1 = 5;
    int[] a1 = (cast(int*)GC.malloc(int.sizeof * n1, ba1))[0 .. n1];

    uint ba2 = GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE;
    int n2 = 5;
    int[] a2 = (cast(int*)GC.malloc(int.sizeof * n2, ba2))[0 .. n2];
    a2[] = 1;

    uint ba3a = GC.BlkAttr.APPENDABLE;
    uint ba3b = GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE;
    int n3 = 5;
    int[][] m1 = (cast(int[]*)GC.malloc((int[]).sizeof * n3, ba3a))[0 .. n3];
    foreach (ref row; m1)
        row = (cast(int*)GC.malloc(int.sizeof * n3, ba3b))[0 .. n3];

    uint ba4a = GC.BlkAttr.APPENDABLE;
    uint ba4b = GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE;
    int n4 = 5;
    int[][] m2 = (cast(int[]*)GC.malloc((int[]).sizeof * n4, ba4a))[0 .. n4];
    foreach (ref row; m2) {
        row = (cast(int*)GC.malloc(int.sizeof * n4, ba4b))[0 .. n4];
        row[] = 1;

So to avoid all that bug-prone mess I suggest to allow the fixed-sized array
syntax for dynamic arrays too:

// program #4
void main() {
    auto a2 = new int[5] = void;

    auto a1 = new int[5] = 1;

    auto m2 = new int[][](5, 5) = void;

    auto m1 = new int[][](5, 5) = 1;

An usage of unitialized memory:

"An Efficient Representation for Sparse Sets" (1993), by Preston Briggs, Linda

>From programming pearls book:

Configure issuemail:
------- You are receiving this mail because: -------

Reply via email to