I have been learning rust recently.
And I stumbled upon a snippet that is really bugging me.
Why does this work
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = s1 + &s2;
println!("{}",s3)
}
And this does not?
fn main() {
let s1 = String::from("Hello, ");
let s2 = String::from("world!");
let s3 = &s1 + s2;
println!("{}",s3)
}
Thank you in advance
From a technical standpoint, it's because String
implements Add<&str>
and Deref<Target=str>
. So the compiler can rewrite your first example, s1 + &s2
, into s1.add (s2.deref())
.
However neither &String
nor &str
implement Add
, so the compiler can't rewrite &s1 + …
into (&s1).add (…)
.
From a language design standpoint, this choice was made because s1 + …
may be done without allocation if there is enough space already allocated after the current contents of s1
, but &s1 + …
would always require an allocation and it was decided to make that allocation explicit. If you want to keep using the original s1
after the operation, you need to either clone it explicitly:
let s3 = s1.clone() + &s2;
or if performance is really that critical, you need to pre-allocate enough memory to hold the result:
let s3 = String::with_capacity (s1.len() + s2.len()) + &s1 + &s2;