如何对 Rust 数组的 2 个可变切片进行操作?

Posted

技术标签:

【中文标题】如何对 Rust 数组的 2 个可变切片进行操作?【英文标题】:How to operate on 2 mutable slices of a Rust array? 【发布时间】:2016-07-14 16:11:34 【问题描述】:

我有一个函数需要对单个数组的两个部分进行操作。 目的是能够构建一个#[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 咒语可以让它继续?

【问题讨论】:

【参考方案1】:

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

没有,但 Rust 的类型系统目前无法检测到您正在对切片的两个不重叠部分进行可变引用。由于这是一个常见的用例,Rust 提供了一个安全的函数来做你想做的事:std::slice::split_at_mut

fn split_at_mut(&amp;mut self, mid: usize) -&gt; (&amp;mut [T], &amp;mut [T])

在一个索引处将一个&amp;mut 一分为二。

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

【讨论】:

A simple playground showing how to use it【参考方案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]);

哇,这真是一场完美的比赛。感谢您找到这个!

【讨论】:

以上是关于如何对 Rust 数组的 2 个可变切片进行操作?的主要内容,如果未能解决你的问题,请参考以下文章

bytes bytearray;切片操作

如何在 Rust 中传递对可变数据的引用?

访问原始 Rust 类型的方法

不可变 - 使用切片更改数组中的元素(无拼接)

如何在 Rust 中修复“.. 在循环的上一次迭代中可变地借用”?

Go切片数组深度解析