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