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.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]
//...
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现