天天看點

d的兩種初化方式不一樣

​​原文​​

struct A
{
    int[] i;
}
struct B
{
    A[] a = [A.init];
}      

​A和B​

​如上,代碼:

auto b1 = B.init;
b1.a[0].i ~= 1;
b1.a ~= A.init;
b1.a[0].i ~= 11;
b1.a[1].i ~= 12;
b1.writeln;

auto b2 = B();
b2.writeln;
//期望相同
B([A([1, 11]), A([12])])
B([A([])])      

期望編譯.但代碼:

B b1;      // auto b1 = B.init;
b1.a[0].i ~= 1;
b1.a ~= A.init;
b1.a[0].i ~= 11;
b1.a[1].i ~= 12;
b1.writeln;

B b2;     // auto b2 = B();
b2.writeln;
//沒有列印期望的
B([A([1, 11]), A([12])])
B([A([1])])      

為什麼?

A[] a = [A.init];      

​問題​

​​在此,它是引用在B的​

​所有副本​

​​中共享的​

​靜态數組執行個體​

​​.幾乎肯定你不想要它.

​​

​B.a[0]​

​​是跨不同預設構造的所有​

​B​

​​的​

​*相同對象*​

​​.

​​

​不要​

​​這樣.隻有​

​基本值​

​​和​

​不變串​

​​才這樣初化.用​

​數組或類對象​

​​,可能得到共享.

如果在​​

​構造器​

​​(需要個​

​參數​

​​)或​

​工廠​

​​函數中初化,會獲得​

​更加一緻​

​​行為,因為​

​每個執行個體​

​​都有​

​自己​

​​的數組.

至于為什麼​​

​B()​

​​和​

​B.init​

​​在此不同,我不知道,可能是​

​編譯器​

​​的​

​一些微妙​

​實作.

我最近實驗:

struct Xml {
    string beg;
    string end = "/>";  // 所有執行個體共享
    // 無配置設定.
// ...
}      

這不是錯誤:

void main()
{
  struct B
  {
    struct A
    {
      int i = 10;
    }
    A[] a = [A.init];
  }

  B[2] b;
  assert(b[0].a.ptr is b[1].a.ptr);
}      

這不是錯誤.他們指向記憶體中​

​A的​

​​完全相同​

​執行個體​

​​:

這裡是:編譯時配置設定了​​

​單個全局​

​​的在所有​

​B.init​

​​執行個體之間共享的​

​A[]​

​.就像如下:

struct B
{
    struct A
    {
        int i = 10;
    }
    static A[] globalArray = [A.init];
    A[] a = globalArray;
}      

我想調整​

​預設構造器​

​​,但​

​構​

​​不能有​

​自定義​

​​版.

添加​​

​帶參構造器​

​​,似乎是個​

​侵改​

​.

有靜态​

​opCall​

​​,也像​

​侵改​

​.

import std.stdio;

struct A
{
    int[] i;
}
struct B
{
    A[] a = [A.init];

    static B opCall()
    {//
        return B.init;
    }
}

void main()
{
    auto b1 = B.init;
    b1.writeln;

    B b2 = B();
    b2.writeln;

    B b3;
    b3.writeln;
}      

​靜态數組​

​​是值類型.​

​複制​

​​靜态數組時,​

​副本​

​​資料​

​存儲​

​​在與​

​原始​

​​數組不同的​

​記憶體塊​

​中:

int[1] a = [1];
int[1] b = a;

assert(&a[0] !is &b[0]);
//記憶體不同      
int[] a = [1];
int[] b = a;

assert(&a[0] is &b[0]);      
int[] a = [1];
int[] b = a.dup;

assert(&a[0] !is &b[0]);
//不同記憶體