Why immutable string can call String::add(mut self, other: &str) [duplicate]

狂风中的少年 提交于 2021-01-28 05:00:30

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!