Как клонировать последний элемент из вектора?

Я пытаюсь написать код, который получает последний элемент некоторого вектора и выполняет различные действия (включая мутацию вектора) в зависимости от этого элемента.

Я пытался так:

#[derive(Clone, PartialEq)]
enum ParseItem {
    Start,
    End,
}

let mut item_vec = vec![ParseItem::End];
loop {
    let last_item = *item_vec.last().clone().unwrap();
    match last_item {
        ParseItem::End => item_vec.push(ParseItem::Start),
        _ => break,
    }
}

И я получаю следующую ошибку:

ошибка: не может выйти из заимствованного контента
let last_item = *item_vec.last().clone().unwrap();

Я думал, клонируя item_vec.last()проблемы с владением будут решены, но, похоже, нет.

Если я попробую то же самое с вектором целых чисел, как это:

let mut int_vec = vec![0];
loop {
    let last_int = *int_vec.last().clone().unwrap();
    match last_int {
        0 => int_vec.push(1),
        _ => break,
    }
}

компилятор не жалуется на заимствования.

Почему мой код не компилируется?

1 ответ

Решение

item_vec.last() является Option<&T>,

item_vec.last().clone() Другой Option<&T>, Это фактически выполняет поверхностную копию ссылки. Это означает, что вы на самом деле ничего не исправили!

Интуитивно понятно, что это имеет смысл - клонирование указателя может вернуть тип значения для хранения непосредственно в стеке, но клон Option<&T> не могу клонировать T потому что это некуда положить.

Это работает, потому что Option<T> на самом деле звонки clone на &T, так Option<&T> звонки clone на &&T, что означает &self параметр в признаке разрешается в self = &T, Это означает, что мы используем impl из Clone за &T:

impl<'a, T: ?Sized> Clone for &'a T {
    /// Returns a shallow copy of the reference.
    #[inline]
    fn clone(&self) -> &'a T { *self }
}

*item_vec.last().clone().unwrap() таким образом, все еще заимствование вектора.

Это можно исправить двумя основными способами. Одним из них является использование Option "s cloned метод, который клонирует внутреннюю ссылку прочь:

item_vec.last().cloned().unwrap()

Это реализовано как map по внутренним данным:

impl<'a, T: Clone> Option<&'a T> {
    /// Maps an Option<&T> to an Option<T> by cloning the contents of the Option.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn cloned(self) -> Option<T> {
        self.map(|t| t.clone())
    }
}

Другой вариант заключается в unwrap и только потом clone ссылка, чтобы получить значение:

item_vec.last().unwrap().clone()
Другие вопросы по тегам