代码之家  ›  专栏  ›  技术社区  ›  user3169543

包含可变切片的结构[重复]

  •  0
  • user3169543  · 技术社区  · 6 年前

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

    我提出了一个带有切片和 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 回复  |  直到 6 年前
        1
  •  3
  •   Peter Hall    6 年前

    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
            }
        }
    }