问题
In stdlib string.rs:
impl Add<&str> for String {
type Output = String;
#[inline]
fn add(mut self, other: &str) -> String {
self.push_str(other);
self
}
}
let s1 = String::from("tic");
let s2 = String::from("tac");
let s = s1 + &s2;// it works
s1 is immutable here, but Add::add(mut self, other: &str) is mut, I just want to know why.
回答1:
You borrow and consume s1
when you use it in the concatenation. If you try to print s1
after the line
let s = s1 + &s2;// it works
,
there will be an error because it is used after move:
3 | let s1 = String::from("tic");
| -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait
...
6 | let s = s1 + &s2;// it works
| -- value moved here
7 | println!("{}{}{}",s,s1,s2);
| ^^ value borrowed here after move
s1
does not need to be mutable as the variable is never mutated the data is moved and mutated to the variable s
.
回答2:
s1 is immutable here
Not exactly. The s1
binding is immutable, but since add
takes ownership of the value it was bound to, it can do what it wants with it (including mutating it). As you don't have access to the value anymore you can't observe changes and it makes no difference to you.
It's not dissimilar to the meatworld: if you lend something to somebody and they have your permission to modify it then they might do so, but if you give something to somebody, whether they modify it is none of your business anymore.
As Simson notes, if you try to reuse s1
after the addition the compiler will reject your code.
来源:https://stackoverflow.com/questions/65682724/why-immutable-string-can-call-stringaddmut-self-other-str