gpt4 book ai didi

pointers - 使用原始指针访问 RefCell> 的 &T 是否安全?

转载 作者:行者123 更新时间:2023-11-29 08:23:36 25 4
gpt4 key购买 nike

我有一个内部使用 HashMap 的类缓存结构:

impl Cache {
fn insert(&mut self, k: u32, v: String) {
self.map.insert(k, v);
}

fn borrow(&self, k: u32) -> Option<&String> {
self.map.get(&k)
}
}

Playground with external mutability

现在我需要内部可变性。自 HashMap不执行 Copy ,我的猜测是 RefCell是要遵循的路径。编写 insert方法很简单,但我遇到了借用功能的问题。我可以返回 Ref<String> , 但因为我想缓存结果,所以我写了一个小的 Ref -包装:

struct CacheRef<'a> {
borrow: Ref<'a, HashMap<u32, String>>,
value: &'a String,
}

value 起这将不起作用引用文献 borrow ,因此无法构造结构。我知道引用始终有效: map 无法更改,因为 Ref 锁定 map 。使用原始指针而不是引用安全吗?

struct CacheRef<'a> {
borrow: Ref<'a, HashMap<u32, String>>,
value: *const String,
}

我是不是忽略了什么?有更好(或更快)的选择吗?我试图避免 RefCell由于运行时开销。

Playground with internal mutability

最佳答案

我将用不安全的版本来补充@Shepmaster 的安全但效率不高的答案。为此,我们将在实用函数中打包一些不安全的代码。

fn map_option<'a, T, F, U>(r: Ref<'a, T>, f: F) -> Option<Ref<'a, U>>
where
F: FnOnce(&'a T) -> Option<&'a U>
{
let stolen = r.deref() as *const T;
let ur = f(unsafe { &*stolen }).map(|sr| sr as *const U);
match ur {
Some(u) => Some(Ref::map(r, |_| unsafe { &*u })),
None => None
}
}

我很确定这段代码是正确的。尽管编译器对生命周期相当不满意,但它们解决了。我们只需要注入(inject)一些原始指针就可以让编译器闭嘴。

有了这个,borrow 的实现变得微不足道:

fn borrow<'a>(&'a self, k: u32) -> Option<Ref<'a, String>> {
map_option(self.map.borrow(), |m| m.get(&k))
}

Updated playground link

效用函数仅适用于 Option<&T> .其他容器(例如 Result )将需要它们自己的修改副本,或者 GAT 或 HKT 以通用实现。

关于pointers - 使用原始指针访问 RefCell<HashMap<T>> 的 &T 是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49364267/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com