参照周りの話
可変参照に対してメソッドを呼ぶとき
Section titled “可変参照に対してメソッドを呼ぶとき”String
型の変数に対して、push_str
メソッドを呼ぶことができる。
fn main() { let mut s = String::from("Hello"); s.push_str("World"); println!("{}", s);}
可変参照を使うと次のようにも書ける。
fn main() { let mut s = String::from("Hello"); let r = &mut s; r.push_str("World"); println!("{}", r);}
ここで疑問なのが、push_str
メソッドはString
型で実装されているので、参照型に対する挙動がどうなっているのか、ということである。
push_str
の実装
Section titled “push_strの実装”push_str
の実装は以下のようになっている。
pub fn push_str(&mut self, string: &str) { self.vec.extend_from_slice(string.as_bytes())}
つまりおおざっぱに書くとこんな感じになっている。
impl String { fn push_str(&mut self, string: &str) { ... }}
push_str
は、&mut self
を受け取るメソッドとなっている。
&mut self
の概念はまだ出てきていないのでわからないが、おそらく、「可変参照を通して自分自身を引数に取る」ということを意味している。
ChatGPTによると、Rustのメソッド呼び出し糖衣構文と言うらしく、mut s: String
の変数に対しては、自動で&mut s
が渡されるらしい。
何にせよ、push_str
はString
型で実装されているものであるので、some_string: &mut String
に対して、some_string.push_str()
と呼び出したときの挙動については別の話になる。
参照型についてこのメソッドを呼ぶ際には、参照外し (deref) が自動的に行われる。 Rustでは、「参照に外してメソッドを呼ぶ」とき、自動で参照外しして本体にアクセスする。
つまり、&mut String
-> String
へと自動的に参照外し:*
が適用される。
そのため実際には、
(*some_string).push_str("World");
と同じ意味になり、可変なString
変数が渡されるようになる。