包含可变切片的结构

时间:2018-12-24 20:53:15

标签: reference rust slice mutable borrowing

我试图了解生命周期,并在结构中存储可变切片。

我想到了这个示例,它带有一个带有切片的结构和一个take函数,该函数将返回n元素(如果存在)并将其余元素存储在结构本身中。此代码无法编译。

fn main() {
    let mut v: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    let mut blah = Blah { slice: &mut v[..] };

    let b = blah.take(5);

    println!("b: {:?}", b);
}

#[derive(Debug)]
struct Blah<'a> {
    slice: &'a mut [u8],
}

impl<'a> Blah<'a> {
    pub fn take(&'a mut self, n: usize) -> Option<Self> {
        if self.slice.len() > n {
            let blah = Blah {
                slice: &mut self.slice[..n],
            };
            self.slice = &mut self.slice[n..];
            Some(blah)
        } else {
            None
        }
    }
}

编译器错误:

error[E0499]: cannot borrow `*self.slice` as mutable more than once at a time
  --> src/main.rs:21:31
   |
15 | impl<'a> Blah<'a> {
   |      -- lifetime `'a` defined here
...
19 |                 slice: &mut self.slice[..n],
   |                             ---------- first mutable borrow occurs here
20 |             };
21 |             self.slice = &mut self.slice[n..];
   |                               ^^^^^^^^^^ second mutable borrow occurs here
22 |             Some(blah)
   |             ---------- returning this value requires that `*self.slice` is borrowed for `'a`

我有一个很大的内存缓冲区,我不想复制。相反,我想通过携带“胖指针”(类似于偏移量+长度)来继续引用相同的内存。

1 个答案:

答案 0 :(得分:2)

Rust编译器无法检测到两个子切片借用不重叠。借用&mut self.slice[..n]时,整个self.slice被视为借用的,因此您就不能借用其余的元素。

有一种方法split_at_mut旨在通过从切片产生两个不相交的可变借位来解决此问题。您的代码可以更新为像这样使用它:

impl<'a> Blah<'a> {
    pub fn take(&'a mut self, n: usize) -> Option<Self> {
        if self.slice.len() > n {
            let (left, right) = self.slice.split_at_mut(n);
            let blah = Blah {
                slice: left
            };
            self.slice = right;
            Some(blah)
        } else {
            None
        }
    }
}