标准Cell结构提供内部可变性,但只允许一些突变方法,例如 set()、swap() 和 replace()。所有这些方法都会改变 Cell 的全部内容。但是,有时需要进行更具体的操作,例如,仅更改单元格中包含的部分数据。
所以我尝试实现某种通用单元格,允许任意数据操作。操作由用户定义的闭包表示,该闭包接受单个参数 - &mut 对 Cell 内部数据的引用,因此用户自己可以决定如何处理 Cell 内部。下面的代码演示了这个想法:
use std::cell::UnsafeCell;
struct MtCell<Data>{
dcell: UnsafeCell<Data>,
}
impl<Data> MtCell<Data>{
fn new(d: Data) -> MtCell<Data> {
return MtCell{dcell: UnsafeCell::new(d)};
}
fn exec<F, RetType>(&self, func: F) -> RetType where
RetType: Copy,
F: Fn(&mut Data) -> RetType
{
let p = self.dcell.get();
let pd: &mut Data;
unsafe{ pd = &mut *p; }
return func(pd);
}
}
// test:
type MyCell = MtCell<usize>;
fn main(){
let c: MyCell = MyCell::new(5);
println!("initial state: {}", c.exec(|pd| {return *pd;}));
println!("state changed to {}", c.exec(|pd| {
*pd += 10; // modify the interior "in place"
return *pd;
}));
}
但是,我对代码有些担心。
它是否安全,即一些安全但恶意的关闭是否可以通过使用这个“通用”单元来打破 Rust 的可变性/借用/生命周期规则?我认为它是安全的,因为内部引用参数的生命周期禁止其在闭包调用时间之外的公开。但我仍然有疑问(我是 Rust 的新手)。
也许我正在重新发明轮子,并且存在一些解决问题的模板或技术?
注意:我在这里发布了这个问题(不是在代码审查中),因为它似乎与语言而不是代码本身(仅代表一个概念)更相关。
[编辑] 我希望零成本抽象没有运行时失败的可能性,所以 RefCell 不是完美的解决方案。