我在 Rust 中有一个数据结构,它被创建并且永远不会改变(就像游戏的规则集)。然后我想在其他结构中引用该数据,但我不希望这些其他结构拥有它,只是“不可变地”引用它。 如果数据在没有更多引用时被删除,那就太好了。 所以 Rc 出现在脑海中。然而,对于借用检查器来说,它似乎拥有该数据。 然后是 RefCell,它可以解决问题。但它也允许可变地借用内部数据,我想防止这种情况,它允许可变性。
让这些成为我的定义:
struct RuleSet { rule1: Rule; ... }
struct GameState{ ruleSet: ??<RuleSet>; ... }
Impl for GameState {
fn do_things(&mut self, rule: &rule){ ... }
}
我想做那样的事情:
let state: GameState = ...;
let def = state.ruleSet.rule1;
state.do_things(def); // <- here it complains: cannot mutably borrow 'state' whlie immutably borrow 'state' (def is part of it)
如果我只是让
ruleSet
是RuleSet
类型,它会抱怨它不能借用state
,因为它是在def
中借来的(从上面的行)因为rule1
是ruleSet
的一部分是它的一部分。
当我使用 Rc
时,它说的是同样的事情,所以它以某种方式认为它对其内容拥有所有权。我可以在取出东西之前克隆Rc
,但这很丑陋。
当我使用RefCell
时,我可以这样访问它:state.ruleSet.borrow().rule1
这非常接近我想要实现的目标,但是 RefCell
支持 borrow_mut()
,我不想要而且我认为它不会引用计数。
所以我主要想让它不可变或分离,这样借用检查器就不会认为我不能在引用父结构时弄乱它。
你想要一个
Rc
(或在并发上下文中为Arc
)不知道为什么你认为克隆它是“丑陋的”但是你必须通过一些操作来增加计数器而clone
就是这样做的.它专为您的用例而设计,当不再使用它时,它会被清理干净,因此每个共享所有者都可以保留一些东西,一生只能束缚'static
.
共享引用的唯一其他选择是
Box::leak
但这不能满足您在不再使用数据时释放数据的要求。
解决整个问题的最好方法是将
ruleSet
踢出GameState
,这样编译器就不会抱怨do_thing
。但是,如果不可能,下面这样的东西怎么样?
impl GameState {
/// Use two different lifetimes.
fn do_things<'s, 'r>(&'s mut self, rule: Option<&'r rule>){
// If `None` is supplied, use `self.ruleSet`.
}
}
这里,
let state: GameState = ...;
let def: Option<&'r Rule> = if (need_to_use_rule1) { None } else { Some(ruleX) };
state.do_things(def);
或者,另一种方法是使用函数而不是方法。
impl GameState {
fn do_things(rule: &rule, other_x: &mut GameState.X, other_y: &mut GameState.Y) { ... }
}
因为,Rust 知道
def
只在 GameState::ruleSet
处借用 let def = ...
,所以可以可变地借用 GameState
的其他成员变量,而 def
存在于堆栈中。