如何借用RefCell <HashMap>,找到一个键,并返回对结果的引用?

Mar*_*ler 14 rust interior-mutability

我有一个RefCell<HashMap>并想借用表,找到一个键,并返回对结果的引用:

use std::cell::RefCell;
use std::collections::HashMap;

struct Frame {
    map: RefCell<HashMap<String, String>>,
}

impl Frame {
    fn new() -> Frame {
        Frame {
            map: RefCell::new(HashMap::new()),
        }
    }

    fn lookup<'a>(&'a self, k: &String) -> Option<&'a String> {
        self.map.borrow().get(k)
    }
}

fn main() {
    let f = Frame::new();
    println!("{}", f.lookup(&"hello".to_string()).expect("blargh!"));
}
Run Code Online (Sandbox Code Playgroud)

(游乐场)

如果我删除RefCell然后一切正常:

struct Frame {
    map: HashMap<String, String>,
}

impl Frame {
    fn lookup<'a>(&'a self, k: &String) -> Option<&'a String> {
        self.map.get(k)
    }
}
Run Code Online (Sandbox Code Playgroud)

在不复制哈希表中的字符串的情况下编写查找函数的正确方法是什么?

Fra*_*gné 16

当你借用a时RefCell,你得到的参考的寿命比RefCells 的短.那是因为引用的生命周期受到返回的守卫的限制borrow().该守卫确保没有其他人可以对该值采取可变引用,直到防护被丢弃.

但是,您试图在不保持守卫的情况下返回值.如果Frame有这样的花了一个方法&self的说法,但试图变异地图(这是可能的RefCell-如果你不需要做,那么沟RefCell,写&mut self上发生变异的地图的方法),你可能会意外地摧毁一个String是别人有提及.这正是借用检查员设计报告的那种错误!

如果地图值实际上是不可变的(即您的类型不允许改变地图的值),您也可以将它们包装Rc在地图中.因此,您可以返回一个克隆Rc<String>(这只会克隆引用计数指针,而不是基础字符串),这将允许您在从函数返回之前释放地图上的借位.

struct Frame {
    map: RefCell<HashMap<String, Rc<String>>>
}

impl Frame {
    fn lookup(&self, k: &String) -> Option<Rc<String>> {
        self.map.borrow().get(k).map(|x| x.clone())
    }
}
Run Code Online (Sandbox Code Playgroud)