我有一个包含2个Vec
的结构体。我想要在修改其中一个的同时遍历另一个。下面是一个示例程序:
use std::slice;
struct S {
a: Vec<i32>,
b: Vec<i32>
}
impl S {
fn a_iter<'a>(&'a self) -> slice::Iter<i32> {
self.a.iter()
}
fn a_push(&mut self, val: i32) {
self.a.push(val);
}
fn b_push(&mut self, val: i32) {
self.b.push(val);
}
}
fn main() {
let mut s = S { a: Vec::new(), b: Vec::new() };
s.a_push(1);
s.a_push(2);
s.a_push(3);
for a_val in s.a_iter() {
s.b_push(a_val*2);
}
}
但是有一个编译错误:
$ rustc iterexample.rs
iterexample.rs:28:9: 28:10 error: cannot borrow `s` as mutable because it is also borrowed as immutable
iterexample.rs:28 s.b_push(a_val*2);
^
note: in expansion of for loop expansion
iterexample.rs:26:5: 29:6 note: expansion site
iterexample.rs:26:18: 26:19 note: previous borrow of `s` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `s` until the borrow ends
iterexample.rs:26 for a_val in s.a_iter() {
^
note: in expansion of for loop expansion
iterexample.rs:26:5: 29:6 note: expansion site
iterexample.rs:29:6: 29:6 note: previous borrow ends here
iterexample.rs:26 for a_val in s.a_iter() {
iterexample.rs:27 println!("Looking at {}", a_val);
iterexample.rs:28 s.b_push(a_val*2);
iterexample.rs:29 }
^
note: in expansion of for loop expansion
iterexample.rs:26:5: 29:6 note: expansion site
error: aborting due to previous error
我了解编译器的报错原因。在for循环中,我使用了self
,因为我仍然在遍历它。
但从理论上讲,应该有一种方法可以实现这一点。我只修改了s.b
,并未修改正在遍历的东西(s.a
)。是否有办法编写程序以演示这种分离,并允许此类程序编译通过?
这是一个更大程序的简化示例,因此我需要保持相同的总体结构(一个具有某些内容的结构体,其中一个将被迭代,另一个将被更新)。
s.b
推送到内存中导致s
在内存中被重新定位,那么对s.a
的引用将无效。不过,你可以使用s.a.clone().iter()
代替s.a.iter()
来解决这个问题。 - Adrians.a.iter
和s.b.push
实际上是可以正常工作的。我怀疑@Rory想要在他们的非简化代码中保持字段私有(或者a_iter
和b_push
可能实际上更复杂,不仅仅是Vec
方法的简单包装)。 - fjhs.b
不会重新定位s
,但会重新定位由s.b
拥有并由其私有ptr
字段指向的内部内存块(请参见Vec
的实现)。 - mdupa_iter
的新错误,提示“借用值的生命周期不够长”。之前的错误“无法将s
作为可变借用,因为它也被作为不可变借用”仍然存在。 - Amandasaurus