Rust 如何借用参照单元格<;HashMap>;,找到一个键,并返回对结果的引用?
我有一个Rust 如何借用参照单元格<;HashMap>;,找到一个键,并返回对结果的引用?,rust,interior-mutability,Rust,Interior Mutability,我有一个RefCell,想借用表,找到一个键,然后返回对结果的引用: use std::cell::RefCell; use std::collections::HashMap; struct Frame { map: RefCell<HashMap<String, String>>, } impl Frame { fn new() -> Frame { Frame { map: RefCell::new(
RefCell
,想借用表,找到一个键,然后返回对结果的引用:
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
借用时,您得到的引用比RefCell
的生命周期短。这是因为引用的生存期受到borrow()
返回的保护的限制。该保护确保在放弃该保护之前,没有其他人可以获取该值的可变引用
但是,您正在尝试返回一个值,而不保持一个保护的活动状态。如果Frame
有一个方法接受了&self
参数,但试图对映射进行变异(这在RefCell
中是可能的-如果您不需要这样做,那么放弃RefCell
并在变异映射的方法上写入&mut self
),您可能会意外地破坏其他人引用的字符串。这正是借用检查器设计用来报告的错误类型
如果映射值实际上是不可变的(即,您的类型不允许对映射值进行变异),您还可以在映射中将它们包装在Rc
中。因此,您可以返回Rc
的克隆(这仅克隆引用计数指针,而不是基础字符串),这将允许您在从函数返回之前释放映射上的借用
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
}
impl帧{
fn查找(&self,k:&String)->选项{
self.map.borrow().get(k.map)(|x | x.clone())
}
}
嘿,谢谢。这是一个很好的解释。我还在学习,所以我一直在和借书检查员搏斗,但这当然是有道理的。我想我不太明白为什么RefCell会起作用——为什么非RefCell版本不也会因为同样的原因导致问题?@MarcMiller:我想现在你已经意识到生锈是所有权和借贷的问题了。通常,这些在编译时被检查,但是有基于不安全的代码的构造存在于编译器中,并在运行时验证正确性RefCell
就是这样一种构造,因此引入它会稍微改变规则;您可以将其视为单线程代码的读写互斥体。@matthieu-m:谢谢您的加入!麻烦你澄清一下好吗?你是说RefCell将其更改为一种writer锁,而不是reader锁,即使我没有进行借用?我真的不想在这里克隆我的返回值,因为我的对象可能相当大,所以我考虑可能做一些类似于ref计数的事情:RefCell@MarcMiller:如果您根本没有使用borrow_mut()
,那么使用RefCell
绝对没有意义。只需将HashMap
直接存储在框架中即可。如果要避免复制/克隆,请返回引用,这就是它们的用途@MarcMiller:RefCell
本质上是一个读写器锁,尽管不是线程安全的;当您.borrow\u mut()
时,它会检查其他人是否已拥有借用(写入程序需要独占访问权限),当您.borrow()
时,它会检查没有写入程序处于活动状态(读卡器获得共享访问权限)。不过,为了让RefCell
保证写入者的排他性,这意味着通过.borrow()
借用的内容不能比防护装置(Ref>的寿命长
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())
}
}