​原文​​​ 改变​​结构​​位置会怎样?所以在​​main()​​时,X结构一定在​​栈​​中,而下面的一定在​​堆​​中,是吧?

import std;

//void main() {

struct X
{
struct Y {
int i = 10;
alias i this;
}
Y[] y = [Y.init];//.1

string toString() {
return y.format!"%s";
}
}

void main() {

X[2] x;//.2
x.writeln; // [[10], [10]]

x[0].y[0] = 0; // [[0], [0]]
x.writeln;

x[0].y.length++;
x[0].y[1] = 1;

x[1].y[0] = 2;
x.writeln; // [[0, 1], [2]]

} /* 输出其他状态
[[10], [10]]
[[0], [0]]
[[2, 1], [2]]
*/

​.1​​这里,

Y[] y = [Y.init];

按​​内存切片​​​声明​​y​​​(可是​​栈或堆​​​),并把它初化为包含​​Y.init​​​的​​1元素​​​数组.
这是​​​D中​​​的​​重要怪癖​​​:每当用​​字面​​​初化​​聚集数组成员​​​时,​​聚集​​​的所有实例都​​*相同*​​​底层数组.
如果想​​​避免​​​,建议在​​构造器​​​中初化​​y​​​.然后会更明确过程.
​​​.2​​,

X[2] x;

这里声明了包含​​2个X元素​​​的​​静态数组​​​,每个​​X​​​实例都包含​​[Y.init]​​​数组​​切片​​​的​​y​​​成员.每个​​X​​​实例都在​​栈​​​上;但是,它们的​​y成员​​​在其他地方,这里为​​[Y.init]​​​数组.
​​​重要​​​:如上,这里​​x[0].y​​​和​​x[1].y​​​,这两个​​不同​​​切片都引用​​[Y.init]​​​该​​相同数组​​.

栈           全局数据
x[0] {
Y[] y; -----+----> [ Y.init ]
} |
x[1] { |
Y[] y; -----'
}

这里

x.writeln;       // [[10], [10]]
x[0].y[0] = 0; // [[0], [0]]

这行是说,在​​x数组​​​的​​第一个​​​元素中,把​​0​​​赋值给​​y切片​​​数组中的​​第一个​​​元素.由于​​x[0].y​​​和​​x[1].y​​​都指向​​同一​​​底层数组,因此​​x[0].y​​​修改​​它​​​会使​​x[1].y​​也修改了.

栈                  全局数组
x[0] {
Y[] y; -----+----> [ 0 ]
} |
x[1] { |
Y[] y; -----'
}

因此​​x[0].y[0]==0​​​及​​x[1].y[0]==0​​​.因为​​x[0].y.ptr==x[1].y.ptr​​​.
这里:

x.writeln;
x[0].y.length++;

此行增加​​x[0].y​​​数组​​长度​​​.由于在程序​​全局数据区域​​​分配的,并按​​1元素​​​字面声明它,因此没有​​扩展空间​​​.
此时,为了​​​兑现​​​延长数组请求,​​druntime​​​会在​​堆​​​上分配​​新数组​​​,并复制​​旧数组​​​,然后​​扩大​​​长度为​​2​​.现在:

栈            全局数据       堆
x[0] {
Y[] y; ----------------> [ 0, 0 ]
}
x[1] {
Y[] y; ----> [ 0 ]
}

关键点:​​x[0].y​​​和​​x[1].y​​​现在指向​​两个​​​位于不同位置的​​不同数组​​​.​​A​​​中变化不再反映在​​B​​​中.
上面显示的​​​[0]​​​数组,原来是​​x[0].y​​​数组,但不再这样,因为​​druntime​​​已在​​堆​​​中​​复制​​​了它,并更新了​​x[0].y​​​以指向​​副本​​​而不是​​源​​​.但是,​​x[1].y​​​继续指向​​原数组​​.

x[0].y[1] = 1;

变成:

栈             全局    堆
x[0] {
Y[] y; -------------> [ 0, 1 ]
}
x[1] {
Y[] y; -----> [ 0 ]
}

这里,

x[1].y[0] = 2;

为:

栈             全局    堆
x[0] {
Y[] y; -------------> [ 0, 1 ]
}
x[1] {
Y[] y; -----> [ 2 ]
}

x.writeln;// [[0, 1], [2]]

显示了上面.

如果把X置为"​​静态构​​",会看到相同输出.

import std;

void main() {
//static
struct X
{
static struct Y {
//...
}}

static struct Bar {
string s;
string toString() {
return s;
}
}

auto list = "sixtwoone".chunks(3);
list.map!(c => c.to!string)
.map!Bar.array.writeln; // [six, two, one]
//...
}