RefCell<X> 和 RefCell<&X> 上的borrow_mut 之间的区别

Kil*_*KRT 5 reference mutability rust interior-mutability

如果我猜std::rc::Rc,就不可能在 Rust 中通过a创建可变借用,您必须使用CellRefCell。但无论如何我无法理解如何使用它们。例如考虑这个简单的例子

use std::cell::RefCell;

struct X (i32);

impl X {
    fn foo(&mut self) {
        self.0 = 0;
    }
}

fn main () {
    let x = X(5);
    let rcx = RefCell::new(&x);

    let mut mutx: std::cell::RefMut<&X> = rcx.borrow_mut();
    (*mutx).foo();
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

16:5: 16:9 error: cannot borrow immutable local variable `mutx` as mutable
16     mutx.foo();
Run Code Online (Sandbox Code Playgroud)

但是,如果我从行中删除引用(并更新类型mutx):

let rcx = RefCell::new(x);
Run Code Online (Sandbox Code Playgroud)

一切安好。但我不明白为什么,因为RefMut::deref_mut() -> &mut T在第 16 行调用的尊重应该&&mut T在第一种情况下返回,而&mut T在第二种情况下。但是由于编译器应该*根据需要应用很多(如果我知道deref 强制是如何工作的),那么RefMut<X>::deref_mut()RefMut<&X>::deref_mut()

编辑:我错误地忘记mut在第 15 行写,因为在链接的示例中写得正确。所以现在是let mut mutx...

She*_*ter 4

问题源于您RefCell. 我不清楚你为什么想要这样的东西。正常模式是将整个值放入RefCell,而不仅仅是一个引用:

\n\n
fn main () {\n    let rcx = RefCell::new(X(5));\n\n    let mut mutx = rcx.borrow_mut();\n    mutx.foo();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

原始问题的问题

\n\n

你有两个复合错误。让我们检查一下整个错误消息:

\n\n
<anon>:16:5: 16:12 error: cannot borrow immutable borrowed content as mutable\n<anon>:16     (*mutx).foo();\n              ^~~~~~~\n<anon>:16:7: 16:11 error: cannot borrow immutable local variable `mutx` as mutable\n<anon>:16     (*mutx).foo();\n                ^~~~\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意第二个错误 \xe2\x80\x94“无法借用不可变局部变量mutx”。那是因为你需要声明mutx变量可变:

\n\n
let mut mutx: std::cell::RefMut<&X> = rcx.borrow_mut();\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将允许mutx参与DerefMut

\n

  • @KillKRT 虽然 Shepmaster 是正确的,但它可以更清楚。您需要了解的是,值具有固定的位置(在堆栈、堆或其他位置)。这些可以是不可变的。但是,当您从一个值移动到另一个值“foo = bar”时,所包含内存的所有权就会转移。此传输可以传输到可变位置,然后该位置可以提供对内容的传递可变访问。但是您不能对引用执行此操作,因为您无法移出引用,因此您永远无法将引用的数据移动到可变位置。 (2认同)
  • @KillKRT `RefCell` 也有点特殊,因为它允许打破可变性的传递性:不可变的 `RefCell` 可以让您对其内容进行可变访问。如果它的内容是一个值,它可以给出`&amp;mut T`。但如果它的内容是一个引用,它只能给你一个“&amp;mut &amp;T”,它允许你修改内部引用指向的位置,但不能修改内部引用指向的值。 (2认同)