eag*_*arn 6 rust borrow-checker
我在 Rust 中有一个 Graph 数据结构:
type NodeIndex = usize;
struct Graph {
nodes: Vec<NodeIndex>,
edges: Vec<(NodeIndex, NodeIndex)>,
}
Run Code Online (Sandbox Code Playgroud)
我想遍历函数内的所有节点并调用一个函数,该函数使用每个节点作为元素来改变图形,例如:
impl Graph {
fn mutate_fn(&mut self) {
for node in self.nodes {
self.mutate_using_node(node);
}
}
fn mutate_using_node(&mut self, node: NodeIndex) {
// mutate self here
}
}
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为我会有不止一个可变引用。我也不能通过 &self,因为那样我就会有一个可变引用和一个不可变引用。这在 Rust 中是如何处理的?
嗯,你确实不能这样做。我可以列举两种普遍适用的主要方法,特别适合您的例子
这种方式可能是其他方式中最难和/或最慢的方式。只需执行借用检查器想要的操作即可:不要混淆可变借用和不可变借用。对于您的情况,这可以像克隆以下节点一样简单mutate_fn
:
let nodes = self.nodes.clone();
for node in nodes {
self.mutate_using_node(node);
}
Run Code Online (Sandbox Code Playgroud)
如果没有太多细节,很难推理,但我认为这是实现该方法的唯一方法。如果您只更改边缘,例如如下所示:
fn mutate_using_node(&mut self, node: NodeIndex) {
for e in &mut self.edges {
if e.0 == node {
std::mem::swap(&mut e.0, &mut e.1);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以简单地通过组合这些函数来处理它:
fn mutate_using_node(&mut self, node: NodeIndex) {
for e in &mut self.edges {
if e.0 == node {
std::mem::swap(&mut e.0, &mut e.1);
}
}
}
Run Code Online (Sandbox Code Playgroud)
因此,一般来说,没有最终的分步指南(除了复制)来拆分代码。它确实取决于代码语义。
那是RefCell
关于。它基本上在运行时处理借用检查规则,如果这些规则被破坏,你会感到恐慌。对于如下所示的情况:
for node in self.nodes.iter().copied() {
for e in &mut self.edges {
if e.0 == node {
std::mem::swap(&mut e.0, &mut e.1);
}
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,这RefCell
不是Sync
,因此它不能在线程之间共享。对于有螺纹的情况Mutex
, 或者RwLock
是一种替代方案。
归档时间: |
|
查看次数: |
333 次 |
最近记录: |