d的数组问题

原文
改变结构位置会怎样?所以在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.init1元素数组.
这是D中重要怪癖:每当用字面初化聚集数组成员时,聚集的所有实例都*相同*底层数组.
如果想避免,建议在构造器中初化y.然后会更明确过程.
.2,

X[2] x;

这里声明了包含2个X元素静态数组,每个X实例都包含[Y.init]数组切片y成员.每个X实例都在上;但是,它们的y成员在其他地方,这里为[Y.init]数组.
重要:如上,这里x[0].yx[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].yx[1].y都指向同一底层数组,因此x[0].y修改会使x[1].y也修改了.

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

因此x[0].y[0]==0x[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].yx[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]
   //...
}
posted @   zjh6  阅读(12)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示