这个问题在这里已有答案:
我有 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!"));
}
如果我删除 RefCell
然后一切正常:
struct Frame {
map: HashMap<String, String>,
}
impl Frame {
fn lookup<'a>(&'a self, k: &String) -> Option<&'a String> {
self.map.get(k)
}
}
在不复制哈希表中的字符串的情况下编写查找函数的正确方法是什么?
1 回答
当您从
RefCell
借用时,您获得的引用的生命周期比RefCell
's. That'更短,因为引用的生命周期受borrow()
返回的保护限制 . 该守卫确保没有其他人可以对该值进行可变引用,直到防守被丢弃 .但是,您试图在不保持守卫的情况下返回值 . 如果
Frame
有一个方法接受&self
参数但试图改变 Map (这可能是RefCell
- 如果你不需要这样做,那么抛弃RefCell
并在改变 Map 的方法上写&mut self
),你可能会意外地摧毁其他人所引用的String
. 这正是借用检查器设计报告的那种错误!如果 Map 值实际上是不可变的(即您的类型不允许改变 Map 的值),您也可以将它们包装在 Map 中的
Rc
中 . 因此,您可以返回Rc<String>
的克隆(这只会克隆引用计数指针,而不是基础字符串),这将允许您在从函数返回之前释放 Map 上的借位 .