本文介绍了如何借用 RefCell<HashMap>、找到键并返回对结果的引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个RefCell,想借表,找一个key,返回一个对结果的引用:

I have a RefCell<HashMap> and want to borrow the table, find a key, and return a reference to the result:

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 然后一切正常:

If I remove the RefCell then everything works okay:

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

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

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

What is the correct way to write the lookup function without copying the string in the hashtable?

推荐答案

当你从 RefCell 借用时,你得到的引用比 RefCell 的生命周期更短's.这是因为引用的生命周期受到 borrow() 返回的守卫限制.该守卫确保在该守卫被删除之前,没有其他人可以对该值进行可变引用.

When you borrow from a RefCell, the reference you get has a shorter lifetime than the RefCell's. That's because the reference's lifetime is restricted by the guard returned by borrow(). That guard ensures that nobody else can take a mutable reference to the value until the guard is dropped.

然而,你试图在不让守卫存活的情况下返回一个值.如果 Frame 有一个接受 &self 参数但试图改变地图的方法(这可以用 RefCell — 如果你不不需要这样做,然后抛弃 RefCell 并在改变地图的方法上编写 &mut self),你可能会不小心破坏一个 String 其他人引用的.这正是借用检查器旨在报告的错误类型!

However, you are trying to return a value without keeping a guard alive. If Frame had a method that took a &self argument but tried to mutate the map (which is possible with RefCell — if you don't need to do that, then ditch the RefCell and write &mut self on the methods that mutate the map), you could accidentally destroy a String that somebody else has a reference to. That is exactly the kind of errors that the borrow checker was designed to report!

如果地图值实际上是不可变的(即您的类型不允许改变地图的值),您还可以将它们包装在地图中的 Rc 中.因此,您可以返回 Rc 的克隆(这只克隆引用计数的指针,而不是底层字符串),这将使您在从函数返回之前释放映射上的借用.

If the map values are effectively immutable (i.e. your type will not allow mutating the map's values), you could also wrap them in an Rc in your map. You could therefore return a clone of the Rc<String> (this only clones the reference-counted pointer, not the underlying string), which would let you release the borrow on the map before returning from the function.

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

这篇关于如何借用 RefCell<HashMap>、找到键并返回对结果的引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-20 09:27