为什么我在将可变引用 &mut 传递给接受泛型类型的函数后无法重复使用它?

18
为什么这段代码无法编译:
fn use_cursor(cursor: &mut io::Cursor<&mut Vec<u8>>) {
    // do some work
}

fn take_reference(data: &mut Vec<u8>) {
    {
        let mut buf = io::Cursor::new(data);

        use_cursor(&mut buf);
    }

    data.len();
}

fn produce_data() {
    let mut data = Vec::new();
    take_reference(&mut data);
    data.len();
}

这种情况下的错误是:

error[E0382]: use of moved value: `*data`
  --> src/main.rs:14:5
   |
9  |         let mut buf = io::Cursor::new(data);
   |                                       ---- value moved here
...
14 |     data.len();
   |     ^^^^ value used here after move
   |
   = note: move occurs because `data` has type `&mut std::vec::Vec<u8>`, which does not implement the `Copy` trait
io::Cursor::new的签名是它获取其参数的所有权。在这种情况下,参数是对Vec的可变引用。
pub fn new(inner: T) -> Cursor<T>

在我看来,这有点说得通;因为Cursor::new拥有其参数的所有权(而不是引用),因此我们无法在以后使用该值。同时,这也有点说不通:实际上,我们只传递了一个可变引用,而且光标之后就超出了作用域。

produce_data函数中,我们还向take_reference传递了一个可变引用,并且在尝试再次使用data时并没有产生错误,这与take_reference内部不同。

我发现可以通过使用Cursor.into_inner()“取回”引用,但手动执行这个操作感觉有点奇怪,因为在正常使用情况下,借用检查器完全可以自己执行它。

除了使用.into_inner()外,是否有更好的解决方法?也许我还没理解借用检查器的其他方面呢?

1个回答

20

通常情况下,当您向函数传递可变引用时,编译器会隐式执行 重新借用。这将产生一个新的借用,其寿命更短。

当参数是泛型的(并且不是形如 &mut T 的形式)时,编译器不会自动执行此重新借用1。但是,您可以通过对现有的可变引用进行解引用,然后再次引用它来手动执行此操作:

fn take_reference(data: &mut Vec<u8>) {
    {
        let mut buf = io::Cursor::new(&mut *data);

        use_cursor(&mut buf);
    }

    data.len();
}

1 — 这是因为当前的编译器架构只允许在强制转换时同时知道源类型和目标类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接