gpt4 book ai didi

rust - 难以理解向量索引操作中的不可变和可变借用

转载 作者:行者123 更新时间:2023-12-03 11:27:04 25 4
gpt4 key购买 nike

我刚开始使用 Rust。我在理解这段代码的可变和不可变借用时遇到了一些麻烦。这是我正在测试的代码。

fn main() {                                                                                                   
let mut list = vec![1,2,3,4,5,6];
let i = 2;
list[list[i]] = list[list[i-1]];
}

编译时出现以下错误:

error[E0502]: cannot borrow `list` as immutable because it is also borrowed as mutable
--> src/main.rs:4:7
|
4 | list[list[i]] = list[list[i-1]];
| -----^^^^----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here

error: aborting due to previous error

当我用这段代码替换上面的代码片段时,

fn main() {                                                                                                   
let mut list = vec![1,2,3,4,5,6];
let i = 2;
let index = list[i];
list[index] = list[list[i-1]];
}

代码可以正常编译和执行。

我的问题是为什么编译器不将其标记为这样的错误?

5 |     list[index] = list[list[i-1]];
| --------------| |
| | | immutable borrow occurs here
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here

赋值的右侧不是不可变借用吗?为什么只将第一个代码片段标记为错误?

Rust 是否有类似 C++ 中的 happens-before 或 sequenced before 关系,以确保右侧的不可变借用在左侧的可变借用之前排序,因此这不是错误?

如果上一个问题的答案是肯定的,那么为什么编译器不能在内部将 list[list[i]] 序列化为 let tmp = list[i];列表[tmp]=...?

最佳答案

这里有一些代码演示了同样的问题,但有点简化。

fn main() {
let mut list: Vec<usize> = vec![1,2,3,4,5,6];
let i: usize = 2;
let place: &mut usize = &mut list[list[i]];
*place = 3;
}

显然,编译器正在做这样的事情:

fn main() {
let mut list: Vec<usize> = vec![1,2,3,4,5,6];
let i: usize = 2;
// mutable borrow of list starts
let r: &mut Vec<usize> = &mut list;
// immutable borrow of list starts
let q: usize = list[i];
// immutable borrow of list ends
// mutable borrow of r starts
let place: &mut usize = &mut r[q];
// place is a mutable borrow derived from r
*place = 3;
// place is dropped, mutable borrow of r ends
// r is dropped, mutable borrow of list ends
}

这段代码工作正常:

fn main() {
let mut list: Vec<usize> = vec![1,2,3,4,5,6];
let i: usize = 2;
let q: usize = list[i]; // immutable borrow begins and ends
let place: &mut usize = &mut list[q]; // mutable borrow begins
*place = 3; // mutable borrow ends
}

关于rust - 难以理解向量索引操作中的不可变和可变借用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66417013/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com