首页 文章

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

提问于
浏览
13

这个问题在这里已有答案:

我有 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!"));
}

playground

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

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

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

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

1 回答

  • 14

    当您从 RefCell 借用时,您获得的引用的生命周期比 RefCell 's. That'更短,因为引用的生命周期受 borrow() 返回的保护限制 . 该守卫确保没有其他人可以对该值进行可变引用,直到防守被丢弃 .

    但是,您试图在不保持守卫的情况下返回值 . 如果 Frame 有一个方法接受 &self 参数但试图改变 Map (这可能是 RefCell - 如果你不需要这样做,那么抛弃 RefCell 并在改变 Map 的方法上写 &mut self ),你可能会意外地摧毁其他人所引用的 String . 这正是借用检查器设计报告的那种错误!

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

    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())
        }
    }
    

相关问题