Rust 中计数不可变引用背后的数据

问题描述 投票:0回答:2

我在 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()
,我不想要而且我认为它不会引用计数。

所以我主要想让它不可变或分离,这样借用检查器就不会认为我不能在引用父结构时弄乱它。

rust reference immutability borrow-checker refcell
2个回答
2
投票

你想要一个

Rc
(或在并发上下文中为
Arc
)不知道为什么你认为克隆它是“丑陋的”但是你必须通过一些操作来增加计数器而
clone
就是这样做的.它专为您的用例而设计,当不再使用它时,它会被清理干净,因此每个共享所有者都可以保留一些东西,一生只能束缚
'static
.

共享引用的唯一其他选择是

Box::leak
但这不能满足您在不再使用数据时释放数据的要求。


0
投票

解决整个问题的最好方法是将

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
存在于堆栈中。

© www.soinside.com 2019 - 2024. All rights reserved.