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