先看一段代码:
void main(){
int[] c = [1,2,3];
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
c.length = 2;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
c.length = 3;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
c.length = 4;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
}
它输出结果如下:
B7D19FB0, B7D19FB4, B7D19FB8,
B7D19FB0, B7D19FB4,
B7D19FB0, B7D19FB4, B7D19FB8,
B7D1CFA0, B7D1CFA4, B7D1CFA8, B7D1CFAC,
可以看到前3行地址相同,后面一行地址不同。为什么?
D语言的数组分配是内存紧凑的,当减小数组长度减小时,只需要修改切片大小而不需要重新分配。当长度变大时,也会检查原来的缓冲区是否够大,以确定是否需要重新分配空间。注意第2次操作时把长度恢复为原来大小时,并非真的恢复了原来的状态,后面长出来的元素会被初始化为默认值。
再来看一个:
void main(){
int[] c = [1,2,3];
int[] d = c;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
foreach(inout int i; d){
writef(&i);
writef(", ");
}
writefln("");
d.length = 2;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
foreach(inout int i; d){
writef(&i);
writef(", ");
}
writefln("");
d.length = 4;
foreach(inout int i; c){
writef(&i);
writef(", ");
}
writefln("");
foreach(inout int i; d){
writef(&i);
writef(", ");
}
writefln("");
}
在执行int[] d = c;以后,d的确是和c共享了存储区。不过在改变d的长度以后,它就和c分道扬镳了。所以int[] d = c不能理解为d是一个指向c的引用,它实际上创建了一个新的数组对象,但并不拷贝数组元素,它和int[] d = c[0 .. length]是等价的,都是数组切片操作。
这个问题让我困惑不已。比如你用char[]表示一个单词,用char[][]表示一行,char[][][]表示多行。如何引用这个单词?你当然可以每次使用lines[i][j],但如果处理步骤很多,这会不会看起来很头大?
看上去应该这样使用:
char[][][] lines;
char[][] line = lines[0];
line.length = line.length + 1;
line[length - 1] = ",";
可惜根据前面的结论,这将无法影响到lines。如果找不到一个引用类型指向数组,有时候使用起来还真是很麻烦。看起来把Line/Word包装成类是个勉强凑合的主意。。。