我有一段需要存储字符串并访问这些字符串引用的代码。我最初编写的代码如下:
struct Pool {
strings : Vec<String>
}
impl Pool {
pub fn new() -> Self {
Self {
strings: vec![]
}
}
pub fn some_f(&mut self) -> Vec<&str> {
let mut v = vec![];
for i in 1..10 {
let string = format!("{}", i);
let string_ref = self.new_string(string);
v.push(string_ref);
}
v
}
fn new_string(&mut self, string : String) -> &str {
self.strings.push(string);
&self.strings.last().unwrap()[..]
}
}
这不通过借用检查器:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:19:30
|
14 | pub fn some_f(&mut self) -> Vec<&str> {
| - let's call the lifetime of this reference `'1`
...
19 | let string_ref = self.new_string(string);
| ^^^^ mutable borrow starts here in previous iteration of loop
...
23 | v
| - returning this value requires that `*self` is borrowed for `'1`
据说借用检查器不够聪明,无法意识到可变借用并未超出对new_string
的调用范围。我尝试将修改结构的部分与检索引用分离,得到了以下代码:
use std::vec::*;
struct Pool {
strings : Vec<String>
}
impl Pool {
pub fn new() -> Self {
Self {
strings: vec![]
}
}
pub fn some_f(&mut self) -> Vec<&str> {
let mut v = vec![];
for i in 1..10 {
let string = format!("{}", i);
self.new_string(string);
}
for i in 1..10 {
let string = &self.strings[i - 1];
v.push(&string[..]);
}
v
}
fn new_string(&mut self, string : String) {
self.strings.push(string);
}
}
这段代码在语义上等价(希望如此)且可以编译通过。然而,将两个for
循环尽可能地合并为一个:
for i in 1..10 {
let string = format!("{}", i);
self.new_string(string);
let string = &self.strings[i - 1];
v.push(&string[..]);
}
会出现类似的借用错误:
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
--> src/main.rs:19:13
|
14 | pub fn some_f(&mut self) -> Vec<&str> {
| - let's call the lifetime of this reference `'1`
...
19 | self.new_string(string);
| ^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
20 | let string = &self.strings[i - 1];
| ------------ immutable borrow occurs here
...
24 | v
| - returning this value requires that `self.strings` is borrowed for `'1`
我有几个问题:
为什么在这种情况下,借用检查器会如此严格,以至于它会延长可变借用的整个循环期间?分析传递给
new_string
的&mut
不泄漏到该函数调用之外难道不可能/非常困难吗?是否可以通过自定义生命周期来解决这个问题,以便我可以返回既改变又返回引用的原始帮助程序?
有没有一种不会打乱借用检查器的不同方式,我可以在其中实现我想要的内容,即具有自我修改并返回引用的结构?
我发现了这个问题,但我不理解答案(它是对问题#2的否定回答吗?毫无头绪)而且大多数其他问题都存在明确的生命周期参数问题。我的代码只使用推断的生命周期。