一个模块中有 Rc<T>s,另一个模块中有 Rc<RefCell<T>>s 引用相同的数据

Posted

技术标签:

【中文标题】一个模块中有 Rc<T>s,另一个模块中有 Rc<RefCell<T>>s 引用相同的数据【英文标题】:Having Rc<T>s in one module and Rc<RefCell<T>>s in another referencing the same data 【发布时间】:2020-06-14 05:27:13 【问题描述】:

我有这样的数据结构:

mod nodes 
    struct Node 
        predecessors: Vec<Rc<Node>>
    

我显然不需要该模块中节点的可变性。我这里也没有循环引用。

但我有另一个模块,其中包含我需要可变性的节点:

pub mod network 
    mod nodes ...

    struct Network 
        nodes: Vec<Vec<Rc<RefCell<Node>>>>
    

我只是想不出一种方法来为节点本身创建Rc&lt;Node&gt;s 以及为Network 创建Rc&lt;RefCell&lt;Node&gt;&gt;s。

您对如何在network 模块中的可变节点旁边的nodes 模块中实现不变性有任何想法吗?

或者除了将Node 结构中的前驱节点的引用声明为Rc&lt;RefCell&lt;Node&gt;&gt; 之外没有其他方法,即使我在这里不需要可变性(我想避免这种情况)?

【问题讨论】:

【参考方案1】:

Rust 有 single ownership。如果NodeRefCell 拥有,则它不能同时由不同的Rc 拥有。

Node 可以通过RefCell 在一处修改时,这些更改不能在Rc&lt;Node&gt; 的其他位置显示。这将违反Rc&lt;Node&gt; 的不变性。

还要注意Node 是一个结构值,而不是指向对象的指针。没有额外的间接层甚至可以在RefCell 和其他Rc 之间共享它。其数据被复制并内联在其容器中。

考虑在这两个地方使用Rc&lt;RefCell&lt;Node&gt;&gt;。如果在两个地方使用相同的数据,它必须在两个地方都支持所有保证,即使您没有利用这一点。

如果您没有同时使用这两种类型,您可以通过解构它(into_innertry_unwrap)并再次构造另一种类型来将其转换为另一种类型。这种转换不是免费的,因为这些类型的物理内存布局不同。

1234563如果您已经拥有对 get_mut 的可变访问权限,那么 RefCell 的成本为零,因此您可以在特定情况下减少它们的开销。

【讨论】:

以上是关于一个模块中有 Rc<T>s,另一个模块中有 Rc<RefCell<T>>s 引用相同的数据的主要内容,如果未能解决你的问题,请参考以下文章

在另一个模块中注入模块并使用注入模块的控制器

如何在Android的另一个模块中调用一个Activity(属于一个模块)?

常?用模块

重新加载已导入另一个模块的模块

python - 常用模块栗子

如何从另一个模块调用导出的内核模块函数?