为什么Vec <T> :: split_at_mut为该范围的其余部分借用了向量?

Mic*_*ski 2 rust borrow-checker

Vec<T> 有两种方法:

fn push(&mut self, value: T)
fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T])
Run Code Online (Sandbox Code Playgroud)

他们都对载体进行了可变引用.但借款范围似乎不同,例如:

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());
}
Run Code Online (Sandbox Code Playgroud)

doesnt_work函数没有编译,说已经有一个可变的借用nums,它结束和函数的结束.如果我忽略从返回的值,问题就消失了split_at_mut.

or1*_*426 5

借入numsin doesnt_work将持续与变量lr存在一样长,因为向量(和向量本身)中的值实际上是借用的,现在只能通过l和来访问r.

您可以通过将letfor lr在结束的范围中放置以便借用也结束来查看此效果.例如,此代码工作正常,但如果您尝试移动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());
}
Run Code Online (Sandbox Code Playgroud)

在您的also_works示例中,您不对结果执行任何操作,因此借用会立即丢失.基本上,编译器可以看到无法通过方法的结果访问向量,因此您可以通过原始向量自由访问它们.