Reputation: 95
#[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);
}
Here compiler correctly tells me:
println!("{:#?}", car1.company);
^^^^^^^^^^^^ value borrowed here after move
move occurs because `car1.company` has type `String`, which does not implement the `Copy` trait
I understand that String instance is on the heap and that is why it cannot be copied, ownership was moved to the car2.company
. I can solve this use-case by something like this:
#[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);
}
Question 1: Is there a better way to do this?
Now my problem with this is that if the struct had many fields clone would create a copy of the car1 instance of the struct just to use its values to be assigned to the car2 instance of struct which itself will store the values.
If x is the memory required to store an instance of the struct Car
,
3x memory required where technically only 2x memory should have been needed.
Question 2: After car2
is instantiated will car1.clone()
go out of scope and hence relinquish the memory?
If yes: this method of clone would be fine as only temporary one extra x memory is needed.
If no: then is there a way to achieve this goal without needed the extra x memory or taking ownership of the binding itself.
Upvotes: 7
Views: 1030
Reputation: 26245
You're essentially asking if ..car1.clone()
performs a partial clone, and only clones the missing fields, i.e. company
for car2
.
Would that be a possible optimization? Possibly, but clone()
could do anything, so it might not be as cut an dry to perform a "partial clone()
". So the answer is no, car1.clone()
is cloned entirely.
Question 1: Is there a better way to do this?
I'm assuming that you're using the update syntax (..
), because you have significantly more fields. However, if not, then to avoid needlessly cloning model
. Then you can explicitly clone and assign car1.company
.
However, I think you already know this. But if you want to avoid the needless clone of model
. Then this is the alternate solution.
let car2 = Car {
company: car1.company.clone(),
model: String::from("987pqr"),
cost: 47000,
};
Question 2: After
car2
is instantiated willcar1.clone()
go out of scope and hence relinquish the memory?
Yes. model
from car1.clone()
is dropped immediately after the assignment to car2
. However, company
is of course not dropped, as that is moved to car2
.
Upvotes: 3