与 Rc<RefCell<T>> 匹配

Eug*_*Sh. 2 pattern-matching ownership rust

考虑以下代码 - 它可以编译并工作:

use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::{Something, Nothing};

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped = Rc::new(RefCell::new(Foo::Nothing));
    //....

    match *wrapped.borrow() {
        Something(x) => println!("{}", x),
        Nothing => println!("Nothing"),
    };        
}
Run Code Online (Sandbox Code Playgroud)

现在我想匹配两个包装的值而不是一个:

use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::{Something, Nothing};

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped1 = Rc::new(RefCell::new(Foo::Nothing));
    let wrapped2 = Rc::new(RefCell::new(Foo::Nothing));
    //....

    match (*wrapped1.borrow(), *wrapped2.borrow()) {
        (Something(x), Something(y)) => println!("{}, {}", x, y),
        _ => println!("Nothing"),
    };        
}
Run Code Online (Sandbox Code Playgroud)

现在这将给出编译错误:

use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::{Something, Nothing};

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped = Rc::new(RefCell::new(Foo::Nothing));
    //....

    match *wrapped.borrow() {
        Something(x) => println!("{}", x),
        Nothing => println!("Nothing"),
    };        
}
Run Code Online (Sandbox Code Playgroud)

我不太明白这两个例子的语义之间的根本区别。为什么会发生这种情况以及使第二个片段起作用的正确方法是什么?

edw*_*rdw 5

    match (*wrapped1.borrow(), *wrapped2.borrow()) {
Run Code Online (Sandbox Code Playgroud)

您在此处创建了一个元组。并且这些值被移动到新创建的元组中。这虽然有效:

use std::rc::Rc;
use std::cell::RefCell;
use crate::Foo::Something;

enum Foo {
    Nothing,
    Something(i32),
}

fn main() {
    let wrapped1 = Rc::new(RefCell::new(Foo::Nothing));
    let wrapped2 = Rc::new(RefCell::new(Foo::Nothing));

    match (&*wrapped1.borrow(), &*wrapped2.borrow()) {
        (Something(x), Something(y)) => println!("{}, {}", x, y),
        _ => println!("Nothing"),
    };        
}
Run Code Online (Sandbox Code Playgroud)

  • 哇,好吧,多亏了这个答案和这个答案,现在所有内容都点击了:/sf/answers/4654631131/。因此:借用返回一个不可变的锁保护“Ref<T>”,如果存在任何可变借用,它可能会发生恐慌,并且如果尚未删除,则会产生可变借用恐慌;`*` 取消引用 `T`,但还没有移出,因为我们立即使用 `&` 进行引用。使用此“&*x.borrow()”语法,“Ref<T>”仅在匹配范围内存在,因此在“match”之后稍后获取可变引用是安全的(持有“Ref”)在变量中需要显式删除) (2认同)