循环变异时,可变借位时间过长

问题描述

我有一段代码需要存储String并访问对这些字符串的引用。我首先将其编写如下:

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`

我有几个问题:

  1. 在这种情况下,为什么借位检查器如此严格,以至于在整个循环期间都将可变的借项扩展到整个循环?是否很难/很难分析传递给&mut的{​​{1}}不会在该函数调用之后泄漏?

  2. 是否可以通过自定义生存期来解决此问题,以便我可以返回原来的助手,该助手既变异又返回引用?

  3. 是否存在一种不同的,更符合Rust惯用的方式,不会让借阅检查器无法实现我想要的目标,即是否具有变异并返回对自身的引用的结构?

我找到了this question,但是我不明白答案(是对#2的否定答案吗?不知道),并且大多数其他问题都存在明确的生命周期参数问题。我的代码仅使用推断的生存期。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)