我知道Rust不支持可变长度数组,但是这让我想知道如何替换它们,因为:
-
我不想在循环中分配和释放一个微小的Vec
-
借用检查器不允许我在循环外移动代码
-
固定大小的数组有很多限制,所以我无法弄清楚如何使用它们
我正在转换的C代码通过调用每一行上的回调来处理图像,传递一小部分指针:
float *tmp[img->channels]; // Small, up to 4 elements
for(int y = 0; y < height; y++) {
for(int ch = 0; ch < img->channels; ch++) {
tmp[ch] = &img->channel[ch]->pixels[width * y];
}
callback(tmp, img->channels);
}
我的Rust尝试(example in playpen):
for y in 0..height {
let tmp = &img.channel.iter().map(|channel| {
&mut channel.pixels.as_ref().unwrap()[width * y .. width * (y+1)]
}).collect();
callback(tmp);
}
但它被拒绝了:
无法使用类型为&mut [f32]的元素从迭代器构建类型[&mut [f32]]的集合
可悲的是,这听起来就像我想要的那样!
我已经尝试使用固定大小的数组,但Rust不支持泛型,所以我不能从迭代器中填充它,并且我不能在类似C的循环中填充它们,因为引用了循环不会比它活得更久 .
特征核心:: iter :: FromIterator <&mut [f32]>未实现类型[&mut [f32]; 4]
从固定大小的数组中获取内存片段的另一种方法也失败了:
let mut row_tmp: [&mut [f32]; 4] = unsafe{mem::zeroed()};
for y in 0..height {
row_tmp[0..channels].iter_mut().zip(img.chan.iter_mut()).map(|(t, chan)| {
*t = &mut chan.img.as_ref().unwrap()[(width * y) as usize .. (width * (y+1)) as usize]
});
cb(&row_tmp[0..channels], y, width, image_data);
}
错误:不能一次多次将img.chan借用为可变的
1 回答
arrayvec是一个可以满足您需求的库 . (另外,您可能需要
iter_mut
和as_mut
而不是iter
和as_ref
. )它在堆栈上分配固定数量的存储空间(此处为4项),其行为类似于
Vec
,其大小有限(最高为编译时指定的容量)但可变 .arrayvec
中的大部分复杂性是处理为可变数量的项目运行析构函数 . 但由于&mut _
没有析构函数,因此您也可以使用固定大小的数组 . 但是你必须使用unsafe
代码并注意不要读取未初始化的项目 . (固定大小的数组不实现FromIterator
,这是Iterator::collect
使用的 . )(Playpen)
Edit :不安全的代码可以替换为:
较短的
[&mut []; 4]
初始化程序语法不适用于此处,因为&mut [_]
不可隐式复制 . 类型注释是必要的,因此您不会得到[&mut [_; 0]; 4]
.