Rust中match语句不可变借用生命周期问题:v[*x]与v[u]的差异
为什么用
*x索引修改Vec会报错,换成u就没问题? 先看这段Rust代码:
fn main() { let mut v = Vec::from([0, 1, 2]); for i in 0..5 { match v.get(i) { Some(x) => { let u: usize = *x; v[*x] = v[*x] + 1; // 编译报错 v[u] = v[*x] + 1; // 正常通过 } None => v.push(i + 1), } } println!("{:?}", v); }
编译时会弹出以下错误:
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable --> src\main.rs:9:17 | 6 | match v.get(i) { | - immutable borrow occurs here ... 9 | v[*x] = v[*x] + 1; // Not OK??? | ^ -- immutable borrow later used here | | | mutable borrow occurs here
核心疑问:明明x和u的值完全一样,为啥用*x当索引修改Vec就不行,换成u就没问题?
问题出在「引用绑定」和「值拷贝」的区别
x是Vec元素的引用,不是值本身
调用v.get(i)返回的Some(x)里,x是&usize类型——它是Vec里某个元素的不可变引用,这个引用会一直有效到整个match分支结束。用
*x索引时,你还在依赖这个引用
写v[*x]的时候,你得先解引用x拿到值,这等于还在使用那个不可变引用。而对Vec做赋值操作(v[索引] = ...)需要可变借用Vec。
Rust的规则是:同一个对象不能同时存在可变借用和不可变借用,所以编译器直接拦下来了。u是独立的拷贝,和原引用没关系let u: usize = *x;这一步是把x指向的数值完整拷贝到了栈上的新变量u里——usize是Copy类型,拷贝后u就是完全独立的,和Vec的引用x彻底没关系了。
用u当索引时,你只是用了一个栈上的普通数值,没有再碰那个不可变引用。这时候对Vec发起可变借用,就不会和任何活跃的不可变引用冲突,编译器就放行。
说白了就是:*x还拴着Vec的不可变引用,而u是脱离了引用约束的独立值,自然不会触发借用冲突。
内容的提问来源于stack exchange,提问作者zhaokai xie
相关产品推荐
相关产品推荐

