我一直在与借阅检查员打架......我想要做的就是:
#[derive(Debug)]
struct SomeStruct {
value: String,
}
impl SomeStruct {
fn new(value: &str) -> SomeStruct {
SomeStruct { value: value.to_string() }
}
fn change_value(&mut self, new_value: &str) {
self.value = new_value.to_string();
}
}
fn main() {
let mut my_vec = vec![
SomeStruct::new("foo"),
SomeStruct::new("bar"),
];
my_vec[0].change_value(my_vec[1].value.as_str());
}
Run Code Online (Sandbox Code Playgroud)
这是我遇到的问题的一个非常通用的版本.这是stderr:
error[E0502]: cannot borrow `my_vec` as immutable because it is also borrowed as mutable
--> src/main.rs:22:30
|
22 | my_vec[0].change_value(my_vec[1].value.as_str());
| ------ ^^^^^^ - mutable borrow ends here
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)
所以借用检查器不允许我借两次向量(一次是可变的,然后又是不可变的),这是我理解的.但令人沮丧的是,我想修改向量中的一个元素,而只读取另一个元素.我是Rust的新手(惊喜!),我不确定我是否已经把我的想法全部包含在所有细节和设计选择中.但这是感觉它应该工作的东西,但却没有.我错过了什么,我能做些什么来使这个(或类似的行为)起作用?任何帮助是极大的赞赏!
我同意,这有点令人困惑.让我们首先看一下,为什么Rust编译器不允许这样做.
索引运算符[]可以重载,这意味着该语言的用户可以指定它的工作方式.Rust尝试最小化编译器具有某些特殊知识的类型的数量.因此,尽管它很受欢迎,但它Vec<T>只是一个由图书馆定义的普通类型.你可以编写自己的,Vec<T>而不告诉编译器!
Vec<T>还重载索引运算符,以允许索引向量.但由于重载可以做任何事情,它总是可以返回向量的第一个元素!如果你假设索引操作符会做这么奇怪的事情,那么不应该允许这段代码:
my_vec[0].change_value(my_vec[1].value.as_str());
Run Code Online (Sandbox Code Playgroud)
因为my_vec[0]和my_vec[1]引用相同的值.
当然,索引运算符并没有以这种愚蠢的方式实现,我们知道这一点.为了获得对向量的不同元素的两个引用(其中至少一个是可变的),我们必须使用一些特殊函数而不是索引运算符.并且有很多方法可以做到:
split_first_mut()split_at_mut()iter_mut() 它返回一个可变引用的迭代器我无法告诉你使用什么方法,因为我不知道你的确切用例.但只是为了修复你的例子,你可以写:
let (head, tail) = my_vec.split_first_mut();
head.change_value(tail[0].value.as_str());
Run Code Online (Sandbox Code Playgroud)