Vec<T>
有两种方法:
fn push(&mut self, value: T)
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T])
他们都对载体进行了可变引用。但借款的范围似乎有所不同,例如:
fn works() {
let mut nums: Vec<i64> = vec![1,2,3,4];
nums.push(5);
println!("{}", nums.len());
}
fn doesnt_work() {
let mut nums: Vec<i64> = vec![1,2,3,4];
let (l,r) = nums.split_at_mut(2);
println!("{}", nums.len());
}
fn also_works() {
let mut nums: Vec<i64> = vec![1,2,3,4];
let _ = nums.split_at_mut(2);
println!("{}", nums.len());
}
doesnt_work
函数没有编译,说nums
已经有一个可变的借位,它结束了,函数结束了。如果我忽略从split_at_mut
返回的值,问题就会消失。
答案 0 :(得分:5)
nums
中doesnt_work
的借用将持续存在变量l
和r
,因为向量中的值(以及向量本身)具有字面意义已被借用,现在只能通过l
和r
访问。
您可以通过将let
和l
的{{1}}放在一个范围内来结束,这样借用也会结束。例如,此代码工作正常,但如果您尝试在范围内移动r
(在大括号内),则它将失败:
println!
在您的fn works() {
let mut nums = vec![1,2,3,4];
{
let (l, r) = nums.split_at_mut(2);
//println!("{}", nums.len()); //println! will fail here
}
println!("{}", nums.len());
}
示例中,您不会对结果做任何事情,因此借款会立即丢失。基本上,编译器可以看到您无法通过方法的结果访问向量,因此您可以通过原始向量自由访问它们。
答案 1 :(得分:2)
让我回答我自己的问题,因为我真正缺少的是生命。此代码编译:
fn maybe_use<'a, 'b>(v1: &'a mut Vec<i64>, v2: &'b mut Vec<i64>) -> &'a mut Vec<i64> {
v1
}
fn main() {
let mut nums1: Vec<i64> = vec![1,2,3,4];
let mut nums2: Vec<i64> = vec![1,2,3,4];
let ret = maybe_use(&mut nums1, &mut nums2);
println!("{}", nums2.len());
}
因为maybe_use的返回类型清楚地表明引用来自第一个参数。如果我们将v2
更改为使用'a
生命周期,则main
会停止编译,因为传递给maybe_use
的两个向量都被视为借用。如果我们完全省略了生命周期,编译器会发出以下错误:
这个函数的返回类型包含一个借来的值,但是 签名并未说明是从
借用的v1
还是v2
最初让我感到惊讶的是(编译器如何知道split_at_mut
返回指向向量的指针?)归结为具有相同生命周期的引用。