2015-09-24 5 views
2

Vec<T> имеет два метода:Почему Vec <T> :: split_at_mut заимствовать вектор для остальной части области?

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

Обратите внимание, что это тот же основной вопрос, что и http://stackoverflow.com/q/32761524/155423. – Shepmaster

ответ

4

Заимствование nums в doesnt_work будет продолжаться до тех пор, пока переменные l и r существует, поскольку значения в векторе (и сам векторе) буквально были заимствованы и теперь доступны только через l и r.

Вы можете увидеть этот эффект, поставив let на номер l и 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()); 
} 

В вашем also_works примере вы ничего не делаете с результатом так заимствование теряется немедленно. В основном компилятор может видеть, что вы не можете получить доступ к вектору через результат метода, чтобы вы могли получить доступ к ним через исходный вектор.

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()); 
} 

Потому что тип return может означать, что ссылка исходит из первого аргумента. Если мы исправим v2, чтобы использовать 'a lifetime, main останавливается комментировать, поскольку оба вектора, перешедших на maybe_use, считаются заимствованными. Если мы вообще опустить всю жизнь, компилятор выдает сообщение об ошибке:

this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from v1 or v2

Так что меня удивило изначально (как компилятор знает split_at_mut возвращает указатели на вектор?) Сводится к ссылкам, имеющих один и тот же срок службы.

+1

У вас получилось, поздравляю! – barjak