Rust函数参数计算顺序为何为正向?Vec交换遇借用冲突疑惑
Rust借用规则:Vec::swap的冲突与Vec::push的例外解析
一、为什么ranks.swap(0, ranks.len() - 1)会触发E0502?
Rust的函数参数遵循从左到右的求值顺序:
- 先计算第一个参数
0,无借用操作; - 再计算第二个参数
ranks.len() - 1,此时会对ranks发起一次不可变借用(因为len()是只读方法); - 最后尝试调用
swap方法,该方法需要对ranks发起可变借用。
由于参数求值阶段的不可变借用尚未结束(借用生命周期覆盖整个参数计算过程),此时同时存在可变和不可变借用,违反了Rust的借用规则,因此触发E0502错误。
Rust选择从左到右的求值顺序是为了消除代码行为的歧义,让所有代码的执行顺序保持一致,避免不同场景下出现不可预测的结果。
二、为什么vec.push(*vec.last().unwrap())能编译通过?
这是因为Rust对方法调用的借用检查有特殊处理逻辑:
- 首先计算所有方法参数:
*vec.last().unwrap()。这里vec.last()发起不可变借用,但该借用的生命周期仅到last()返回的临时引用被解引用为止——一旦完成解引用得到具体数值,这个不可变借用就立即结束了; - 所有参数计算完成后,才会调用
push方法,此时发起的可变借用与之前的不可变借用没有时间重叠。
简单来说,方法调用的参数借用和方法接收者的借用是分阶段进行的,只要参数计算完成后借用就结束,就不会和后续的可变借用冲突。
三、更简洁的Vec首尾元素交换写法
如果不想先存储长度,可以利用first_mut和last_mut同时获取首尾的可变引用,编译器会自动检查这两个引用不重叠,因此可以安全交换:
use std::mem; let mut ranks = vec![1, 2, 3, 4]; if let (Some(first), Some(last)) = (ranks.first_mut(), ranks.last_mut()) { mem::swap(first, last); }
这个写法还额外处理了空Vec或单元素Vec的边界情况,避免了索引越界的风险。
内容的提问来源于stack exchange,提问作者rustafari
相关产品推荐
相关产品推荐

