这个问题在这里已有答案:
我有一个函数,它将从Vec返回对现有项的引用,或者将新项推送到Vec并返回对该现有项的引用。我创建了一个基本的例子来说明我想要做的事情:
struct F {
x: Vec<Vec<String>>,
}
impl F {
fn foo(&mut self, s: String) -> &[String] {
for strings in &self.x {
if strings.contains(&s) {
return &strings;
}
}
self.x.push(vec![s]);
&self.x[self.x.len() - 1]
}
}
但是当我尝试编译它时,我得到一个关于生命期的错误:
error[E0502]: cannot borrow `self.x` as mutable because it is also borrowed as immutable
--> src/lib.rs:13:9
|
6 | fn foo(&mut self, s: String) -> &[String] {
| - let's call the lifetime of this reference `'1`
7 | for strings in &self.x {
| ------- immutable borrow occurs here
8 | if strings.contains(&s) {
9 | return &strings;
| -------- returning this value requires that `self.x` is borrowed for `'1`
...
13 | self.x.push(vec![s]);
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
我不明白这个错误,因为在我看来,第7行的不可变借用保证不再存在于第13行,因为该函数将在第13行之前返回,或者for循环将结束,并且借用应该以它结束。我错过了什么?
我认为这是当前借阅检查器的限制,您可以这样做:
struct F {
x: Vec<Vec<String>>,
}
impl F {
fn foo(&mut self, s: String) -> &[String] {
let ret = self.x.iter().position(|strings| strings.contains(&s));
if let Some(ret) = ret {
&self.x[ret]
} else {
self.x.push(vec![s]);
&self.x.last().unwrap()
}
}
}
Stargateur is right和借阅检查器无法证明您的代码是正确的。我们必须帮助它。
另一种可能性是在迭代Vec
s时使用索引。
struct F {
x: Vec<Vec<String>>,
}
impl F {
fn foo(&mut self, s: String) -> &[String] {
for (i, strings) in self.x.iter().enumerate() {
if strings.contains(&s) {
return &self.x[i];
}
}
self.x.push(vec![s]);
self.x.last().unwrap()
}
}
(也可以使用slice::last
而不是手动获取索引。更清楚你想做什么)。