以下代码段以3种方式执行相同的操作。
use std::collections::HashMap;
struct Foo {
cache: HashMap<String, String>,
}
impl Foo {
fn get_cached(&mut self, key: &String) -> &String {
if !self.cache.contains_key(key) {
self.cache.insert(key.clone(), String::from("default"));
}
self.cache.get(key).unwrap()
}
fn show_impl(&self, what: &String) {
println!("{}", what);
}
pub fn show1(&mut self, key: &String) {
println!("{}", self.get_cached(key));
}
pub fn show2(&mut self, key: &String) {
if !self.cache.contains_key(key) {
self.cache.insert(key.clone(), String::from("default"));
}
self.show_impl(self.cache.get(key).unwrap());
}
// This does not compile
pub fn show3(&mut self, key: &String) {
self.show_impl(self.get_cached(key));
}
}
fn main() {}
show3
没有编译,给出以下错误:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:28:24
|
28 | self.show_impl(self.get_cached(key));
| ---- ^^^^ - immutable borrow ends here
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
据我所知,show3
的问题不是可变性,而是双重借用:self
的借用被赠送给get_cached
而不是get_cached
。 t end因为self
返回对{{1}}中包含的内容的引用。这是否正确?
如何实现在自我中查找可变缓存中的值并将引用传递给另一个自我方法的预期目标?
答案 0 :(得分:2)
Rust目前还没有很好地处理这种缓存。
最好的解决方案是完全避免这个问题。 show_impl
真的需要成为Foo
的方法吗?如果没有,您可以定义新特征并为String
实施。例如:
trait ShowImpl: std::fmt::Display {
fn show_impl(&self) {
println!("{}", self);
}
}
impl ShowImpl for String {}
然后只需在字符串show_impl
self.get_cached(key).show_impl();
即可
以下是使用UnsafeCell
的解决方案。我不确定它是否正常工作。虽然它编译,但使用不安全的代码意味着编译器不再能保证安全。
use std::collections::HashMap;
use std::cell::UnsafeCell;
struct Foo {
cache: UnsafeCell<HashMap<String, String>>,
}
impl Foo {
fn get_cached(&self, key: &String) -> &String {
unsafe {
if !(*self.cache.get()).contains_key(key) {
(*self.cache.get()).insert(key.clone(), String::from("default"));
}
(*self.cache.get()).get(key).unwrap()
}
}
fn show_impl(&self, what: &String) {
println!("{}", what);
}
pub fn show1(&mut self, key: &String) {
println!("{}", self.get_cached(key));
}
pub fn show2(&mut self, key: &String) {
unsafe {
if !(*self.cache.get()).contains_key(key) {
(*self.cache.get()).insert(key.clone(), String::from("default"));
}
self.show_impl((*self.cache.get()).get(key).unwrap());
}
}
pub fn show3(&self, key: &String) {
self.show_impl(self.get_cached(key));
}
}
fn main() {}
答案 1 :(得分:0)
您可以尝试在&mut
self
上添加show_impl
,如
...
fn show_impl(&self, what: &String)
...
所以它不会变得混乱。