How to use clone_from
correctly
The Clone
trait contains the function clone_from
which can “reuse the resources of a to avoid unnecessary allocations”. This can make cloning from one Vec
to another as cheap as calling memcpy
.
Unfortunately this does not yet have a specialisation for the derive
macro, and clone_from
is not defined recursively.
This means the derived clone_from
is instead a slow clone
. This is illustrated by the following snippet (playground):
struct Foo;
impl Clone for Foo {
fn clone(&self) -> Self {
println!("Cloned Foo");
Self
}
fn clone_from(&mut self, _source: &Self) {
println!("Cloned from Foo");
*self = Foo
}
}
struct Bar(Foo);
impl Clone for Bar {
fn clone(&self) -> Self {
Self(self.0.clone())
}
fn clone_from(&mut self, source: &Self) {
self.0.clone_from(&source.0)
}
}
#[derive(Clone)]
struct FooBar(Foo);
fn main() {
println!("Cloning Foo");
let foo = Foo;
let mut foo2 = foo.clone();
// prints "Cloning Foo"
foo2.clone_from(&foo);
// prints "Cloned from Foo"
println!();
println!("Cloning Bar");
let bar = Bar(Foo);
let mut bar2 = bar.clone();
// prints "Cloned Foo"
bar2.clone_from(&bar);
// prints "Cloned from Foo"
println!();
println!("Cloning FooBar");
let foobar = FooBar(Foo);
let mut foobar2 = foobar.clone();
// prints "Cloned Foo"
foobar2.clone_from(&foobar);
// prints "Cloned Foo"
}
which shows FooBar
never calls clone_from
, and instead uses the Clone::clone()
default implementation.
For your own collections and larger types you should consider manually implementing clone_from
, which makes clone_from
as cheap as was intended.