Tom*_*omo 8 rust borrow-checker
我有一个struct包含trait对象的可变引用:
trait Task {
fn do_it(&mut self);
}
struct Worker<'a> {
tasks: Vec<&'a mut Task>,
}
Run Code Online (Sandbox Code Playgroud)
在一个方法中Worker,我想迭代任务并调用它们do_it:
impl<'a> Worker<'a> {
pub fn work(&mut self) {
for task in self.tasks.iter() {
self.work_one(*task);
}
}
fn work_one(&self, task: &mut Task) {
task.do_it();
}
}
Run Code Online (Sandbox Code Playgroud)
可悲的是,借阅检查员不允许我这样做:
error[E0389]: cannot borrow data mutably in a `&` reference
--> src/main.rs:12:27
|
12 | self.work_one(*task);
| ^^^^^ assignment into an immutable reference
Run Code Online (Sandbox Code Playgroud)
我不能制作Worker泛型,因为我希望它能够保存多种类型的任务.我还需要任务变得可变.我怎么在Rust中做到这一点?
Arj*_*jan 15
您正在调用tasks.iter()哪个生成对元素的不可变引用Vec.你真的回来了&&mut Task,一个可变的引用的不可变引用(这就是Rust编译器抱怨的原因).
要解决这个问题,请调用tasks.iter_mut()获取可变引用的迭代器.
第二个问题是将定义work_one称为方法.你已经self在迭代时借用了一个可变引用,所以你不能再获得另一个借用.
工作示例(游乐场):
trait Task {
fn do_it(&mut self);
}
struct Worker<'a> {
tasks: Vec<&'a mut Task>,
}
impl<'a> Worker<'a> {
pub fn work(&mut self) {
for task in self.tasks.iter_mut() {
Worker::work_one(*task);
}
}
fn work_one(task: &mut Task) {
task.do_it();
}
}
Run Code Online (Sandbox Code Playgroud)
还是要获得self在work_one此解决方法可以使用.这基本上只是交换两个向量,因此您self在迭代时不会实际借用,然后将其交换回来.这很难看,这里可能有更好的模式,也许其他人会建议更好的东西.
pub fn work(&mut self) {
let mut tasks = vec![];
mem::swap(&mut tasks, &mut self.tasks);
for task in tasks.iter_mut() {
self.work_one(*task);
}
mem::swap(&mut tasks, &mut self.tasks);
}
Run Code Online (Sandbox Code Playgroud)
@Veedrac建议的更好的选择:
fn work(&mut self) {
let mut tasks = mem::replace(&mut self.tasks, Vec::new());
for task in &mut tasks {
self.work_one(*task);
}
self.tasks = tasks;
}
Run Code Online (Sandbox Code Playgroud)
您需要对每个项目都有一个可变引用。iter返回不可变的引用。并且对可变变量的不可变引用本身并不可变。使用iter_mut或for task in &mut self.tasks代替。
然后,最简单的事情就是内联work_one到work:
pub fn work(&mut self) {
for task in self.tasks.iter_mut() {
task.do_it()
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,将其分成两个函数是相当痛苦的。你必须保证调用self.work_one不会修改self.tasks。Rust 不会跨函数边界跟踪这些内容,因此您需要拆分所有其他成员变量并将它们单独传递给函数。
也可以看看:
| 归档时间: |
|
| 查看次数: |
5633 次 |
| 最近记录: |