Rust 可变多维数组作为函数参数
在RustC1.0.0中,我想编写一个函数,该函数可以对调用者提供的二维数组进行变异。我希望这能奏效:Rust 可变多维数组作为函数参数,rust,Rust,在RustC1.0.0中,我想编写一个函数,该函数可以对调用者提供的二维数组进行变异。我希望这能奏效: fn foo(x: &mut [[u8]]) { x[0][0] = 42; } fn main() { let mut x: [[u8; 3]; 3] = [[0; 3]; 3]; foo(&mut x); } 它无法编译: $ rustc fail2d.rs fail2d.rs:7:9: 7:15 error: mismatched types:
fn foo(x: &mut [[u8]]) {
x[0][0] = 42;
}
fn main() {
let mut x: [[u8; 3]; 3] = [[0; 3]; 3];
foo(&mut x);
}
它无法编译:
$ rustc fail2d.rs
fail2d.rs:7:9: 7:15 error: mismatched types:
expected `&mut [[u8]]`,
found `&mut [[u8; 3]; 3]`
(expected slice,
found array of 3 elements) [E0308]
fail2d.rs:7 foo(&mut x);
^~~~~~
error: aborting due to previous error
我相信这告诉我,我需要以某种方式为函数提供一个切片,但我不知道如何构造它
如果我在函数签名中硬编码嵌套数组的长度,它就会“起作用”。这是不可接受的,因为我希望函数在任意维度的多维数组上操作:
fn foo(x: &mut [[u8; 3]]) { // FIXME: don't want to hard code length of nested array
x[0][0] = 42;
}
fn main() {
let mut x: [[u8; 3]; 3] = [[0; 3]; 3];
foo(&mut x);
}
tldr;向多维数组传递引用的任何零成本方法,以便函数使用$x[1][2]=3;$之类的语句 这归结为内存布局的问题。假设一个类型
T
的大小在编译时是已知的(这个约束可以写T:Sized
),那么[T;n]
的大小在编译时是已知的(它占用的内存是T
的两倍);但是[T]
是一种无大小的类型;它的长度在编译时是未知的。因此,它只能通过某种间接方式使用,例如引用(&[T]
)或框(box
),尽管这具有有限的实用价值,使用Vec
,您可以添加和删除项,而无需每次使用过度分配进行重新分配)
没有大小的类型的片段没有意义;这是允许的原因,我不清楚,但你永远不能有一个实际的例子。(Vec
,相比之下,需要T:Sized
)
&[T;n]
可以强制到&[T]
,并将&mut[T;n]
强制到&mut[T]
,但这仅适用于最外层;slice的内容是固定的(您需要创建一个新的数组或向量来实现这种转换,因为每个项的内存布局是不同的)。这样做的结果是,数组可以用于一维工作,但对于多维工作,数组会分解。数组目前在Rust中属于二等公民,在该语言支持使切片在长度上通用之前,数组将一直处于二等公民的地位,这很可能最终会实现
我建议您使用一维数组(适用于方形矩阵,按x*width+y
或类似方式索引)或向量(Vec
)。可能已经有一些库对合适的解决方案进行了抽象。您可能对通用值参数和相应的PR感兴趣