如何操作Rust数组的2个可变片?

时间:2016-03-27 07:04:38

标签: rust slice lifetime

我有一个需要在单个阵列的两个部分上运行的功能。 目的是能够构建一个#[nostd]分配器,它可以将更大数组的变量片返回给调用者,并挂起到数组的其余部分以供将来分配。

以下是失败的示例代码:

fn split<'a>(mut item: &'a mut [i32], place: usize) -> (&'a mut [i32], &'a mut [i32]) {
    (&mut item[0..place], &mut item[place..])
}

fn main() {
    let mut mem: [i32; 2048] = [1; 2048];
    let (mut array0, mut array1) = split(&mut mem[..], 768);
    array0[0] = 4;
    println!("{:?} {:?}", array0[0], array1[0]);
}

错误如下:

error[E0499]: cannot borrow `*item` as mutable more than once at a time
 --> src/main.rs:2:32
  |
2 |     (&mut item[0..place], &mut item[place..])
  |           ----                 ^^^^ second mutable borrow occurs here
  |           |
  |           first mutable borrow occurs here
3 | }
  | - first borrow ends here

这种模式对于就地快速排序等也很有帮助。

对同一个数组的非重叠切片有两个可变引用有什么不安全的吗?如果在纯Rust中没有办法,是否有一个“安全”unsafe咒语可以继续进行?

2 个答案:

答案 0 :(得分:12)

  

对同一个数组的非重叠切片有两个可变引用有什么不安全的吗?

目前还没有,但Rust的类型系统目前无法检测到您是否对片的两个非重叠部分进行了可变引用。由于这是一个常见的用例,Rust提供了一个安全的功能来完全按照你想要的方式执行:std::slice::split_at_mut

  

fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T])

     

将一个&mut分成两个索引。

     

第一个将包含[0, mid)的所有索引(不包括索引)   mid本身,第二个将包含来自[mid, len)的所有索引   (不包括索引len本身)。

答案 1 :(得分:2)

最终代码是:

fn main() {
    let mut mem : [i32; 2048] = [1; 2048];
    let (mut array0, mut array1) = mem[..].split_at_mut(768);
    array0[0] = 4;
    println!("{:?} {:?}", array0[0], array1[0]);
}
哇,这是一场如此完美的比赛。谢谢你找到了这个!