Как клонировать последний элемент из вектора?
Я пытаюсь написать код, который получает последний элемент некоторого вектора и выполняет различные действия (включая мутацию вектора) в зависимости от этого элемента.
Я пытался так:
#[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()