【发布时间】:2020-12-19 20:44:57
【问题描述】:
我有这个结构:
struct PhysicsState {
nodes: Vec<Node>,
edges: Vec<Edge>,
}
我试图理解为什么这段代码会编译:
impl PhysicsState {
fn remove_edge(&mut self, edge_index: usize) {
let edge = &self.edges[edge_index]; // first borrow here
// update the edge-index collection of the nodes connected by this edge
for i in 0..2 {
let node_index = edge.node_indices[i];
self.nodes[node_index].remove_edge(edge_index); // second (mutable) borrow here ?
}
}
}
虽然失败:
impl PhysicsState {
pub fn edge_at(&self, edge_index: usize) -> &Edge {
&self.edges[edge_index]
}
pub fn node_at_mut(&mut self, node_index: usize) -> &mut Node {
&mut self.nodes[node_index]
}
fn remove_edge(&mut self, edge_index: usize) {
let edge = self.edge_at(edge_index); // first (immutable) borrow here
for i in 0..2 {
let node_index = edge.node_indices[i];
self.node_at_mut(node_index).remove_edge(edge_index); // second (mutable) borrow here -> ERROR
}
}
}
}
我原来用的是第一个版本,后来改成第二个,才发现失败了。
对我来说它失败是有道理的。 self 显然先是作为不可变的,然后是可变的,这正如预期的那样失败了。
我不明白的是:第一个版本是如何工作的?
很明显,第一个借用(获取&Edge)必须在整个 for 循环中保持活动状态,因为它在那里使用。但它是如何设法从self 获得对Node 的额外可变引用呢?
第二个版本编译器返回的错误是:error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
为什么我在使用第一个版本时没有收到此错误?
如果您想知道:
- Node 和 Edge 是简单的结构,没有实现 Copy,所以这不是这里发生的事情
- 我想切换到第二个版本的原因是,其中的两个附加函数实际上包含要使用的类型转换,为了便于阅读,我在此处将其删除,但我必须在我的代码中到处重复没有这些功能。
也许我可以改用宏来实现相同的效果,但总的来说我只想知道这里的借用是如何工作的,因为在我看来我对它有某种误解。
谢谢!
【问题讨论】:
标签: rust lifetime self borrow-checker borrowing