#rust
#Ржавчина
Вопрос:
#[derive(Debug)]
struct Car {
company: String,
model: String,
cost: i32
}
fn main() {
let car1 = Car {
company: String::from("Ford"),
model: String::from("123xyz"),
cost: 50000
};
let car2 = Car {
model: String::from("987pqr"),
cost: 47000,
..car1
};
println!("{:#?}", car2);
println!("{:#?}", car1.company);
}
Здесь компилятор правильно сообщает мне:
println!("{:#?}", car1.company);
^^^^^^^^^^^^ value borrowed here after move
move occurs because `car1.company` has type `String`, which does not implement the `Copy` trait
Я понимаю, что экземпляр String находится в куче, и именно поэтому его нельзя скопировать, право собственности было перемещено в car2.company
. Я могу решить этот вариант использования примерно так:
#[derive(Debug, Clone)]
struct Car {
company: String,
model: String,
cost: i32
}
fn main() {
let car1 = Car {
company: String::from("Ford"),
model: String::from("123xyz"),
cost: 50000
};
let car2 = Car {
model: String::from("987pqr"),
cost: 47000,
..car1.clone()
};
println!("{:#?}", car2);
println!("{:#?}", car1.company);
}
Вопрос 1: Есть ли лучший способ сделать это?
Теперь моя проблема заключается в том, что если в структуре было много полей, clone создал бы копию экземпляра car1 структуры только для того, чтобы использовать ее значения для присвоения экземпляру car2 структуры, который сам будет хранить значения. Если x — это память, необходимая для хранения экземпляра struct Car
,
- car1: x
- car1.clone: x
- car2: x
требуется 3x памяти, где технически должно было потребоваться только 2x памяти.
Вопрос 2: После car2
создания экземпляра car1.clone()
выйдет из области видимости и, следовательно, откажется от памяти?
Если да: этот метод клонирования подойдет, поскольку требуется только временная дополнительная память x.
Если нет: тогда есть ли способ достичь этой цели без необходимости использования дополнительной памяти x или получения права собственности на саму привязку.
Ответ №1:
По сути, вы спрашиваете, ..car1.clone()
выполняет ли частичное клонирование и только клонирует недостающие поля, т. Е. company
for car2
.
Будет ли это возможной оптимизацией? Возможно, но clone()
может сделать что угодно, поэтому может быть не так просто выполнить «частичное clone()
«. Итак, ответ отрицательный, car1.clone()
полностью клонирован.
Вопрос 1: Есть ли лучший способ сделать это?
Я предполагаю, что вы используете синтаксис обновления ( ..
), потому что у вас значительно больше полей. Однако, если нет, то, чтобы избежать ненужного клонирования model
. Затем вы можете явно клонировать и назначать car1.company
.
Однако, я думаю, вы это уже знаете. Но если вы хотите избежать ненужного клонирования model
. Тогда это альтернативное решение.
let car2 = Car {
company: car1.company.clone(),
model: String::from("987pqr"),
cost: 47000,
};
Вопрос 2: После
car2
создания экземпляраcar1.clone()
выйдет из области видимости и, следовательно, откажется от памяти?
Да. model
from car1.clone()
удаляется сразу после назначения to car2
. Однако, company
конечно, не отбрасывается, поскольку он перемещается car2
.