I run this code to proof the the difference, All address are different.
#[derive(Clone, Debug)]
#[allow(unused)]
struct Settings {
volume: u16,
}
fn main() {
let settings = &Settings { volume: 10 };
let a = (*settings).clone(); // (1)
let b = settings.clone(); // (2)
println!("address of 'settings' point to: {:p}", settings);
println!("address of 'a': {:p}", &a);
println!("address of 'b': {:p}", &b);
}
Output:
address of 'settings' point to: 0x55e784c480a8
address of 'a': 0x7ffebad638b4
address of 'b': 0x7ffebad638b6
I also read the Trait clone on standard document. They said:
Calling clone always produces a new value. However, for types that are references to other data (such as smart pointers or references), the new value
may
still point to the same underlying data, rather than duplicating it. See Clone::clone for more details.
So, It might not deep clone variable if we use reference clone?
Ultimately it's up to individual types to implement Clone
, but deriving Clone
will always do a “deep” clone — meaning it will clone the fields using their implementation, which might not be deep as in the case of e.g. Rc
.
The question is what exactly is being cloned. Since the signature is clone(&self) -> Self
,
T
it will add a reference before calling and then proceed to the step below.&T
, it will return a T
.So, for instance, cloning &&U
will return &U
. Here is perhaps an instructive example:
#[derive(Clone)]
struct S<'a> {
x: &'a u16,
}
fn main() {
let settings = &S { x: &10 };
let a: S = (*settings).clone();
let b: S = settings.clone();
let c: &S = (&settings).clone(); // clippy warning: clone on a double reference
println!("address of 'settings' point to: {:p}", settings);
println!("address of 'a': {:p}, {:p}", &a, a.x);
println!("address of 'b': {:p}, {:p}", &b, b.x);
println!("address of 'c': {:p}, {:p}", c, c.x);
}
address of 'settings' point to: 0x1000b0060
address of 'a': 0x16fd95d38, 0x1000a3a30
address of 'b': 0x16fd95d40, 0x1000a3a30
address of 'c': 0x1000b0060, 0x1000a3a30
Note that settings
and c
(which are references) point to the same location, as do all the x
s, because in both cases the clone of a reference is itself.
Another thing of note, which I'll mention here even though it's tangential to the question asked, is that auto-deref rules determine what T
is when calling clone()
. For instance, when T: Clone
then if t: T
then t.clone()
tries to call <T as Clone>::clone(&t)
(which returns a T
). But when T: !Clone
— common cases being str
and [U]
— then auto-deref doesn't call <T as Clone>::clone(&t) -> T
(because it doesn't exist) but rather <&T as Clone>::clone(&&t) -> &T
, and so the reference, not the value, is cloned — and indeed it's not possible to “deep clone” a &str
because you cannot have a str
not behind a reference.