LoginSignup
22
2

More than 1 year has passed since last update.

Rustの文字列結合はどうしてString+&strなのか

Last updated at Posted at 2022-01-29

TL; DR;

文字列の2項演算 + が String + &str になっている理由:

  • 効率よく計算するため一方はムーブ(String)になっている
  • 足されるほうは借用で事足りるため借用(&str)になっている

2つの文字列型

Rust には2つの文字列型があります。

  • &str - 文字列スライスとも呼ばれるプリミティブな文字列型。
  • String - 標準ライブラリの提供する文字列型。文字列操作などに使う。

ざっくり理解すると借用が &str で、所有権があるのが String と覚えておくとよさそうです。

&strString は相互に変換できます。

// 文字列リテラルは &str
let s = "hello";

// String の初期化
let s = String::from("hello");

// &str -> String
let s = "hello".to_string();

// String -> &str
let s = String::from("hello").as_str();

2項演算 + でコンパイルが通るのは?

それではクイズ。文字列は2項演算 + で結合できますが、次の4つのパターンのうち、コンパイルが通るのはどれでしょうか?

// &str + &str
"hello" + "world";

// String + &str
String::from("hello") + "world";

// &str + String
"hello" + String::from("world");

// String + String
String::from("hello") + String::from("world");

正解は、2番目の String + &str です。他の3つはコンパイルエラーになります。

なぜ String + &str なのか

なぜ文字列の結合 + は String + &str だけが可能なのでしょうか。答えは2項演算 + の定義にあります。

2項演算 + はトレイト std::ops::Add が実装されている型で使えます。

2項演算は関数呼び出しのシンタックスシュガーと考えられるので、左の項と右の項は関数に与える引数と同じように、Rust の所有権の考え方が適用されます。

そこで、所有権の観点から考えてみましょう。

String は所有者、&str は借用なので、上で考えた4パターンは足し算に与える引数を

  • (借用) + (借用)
  • (ムーブ) + (借用)
  • (借用) + (ムーブ)
  • (ムーブ) + (ムーブ)

というパターンで考えていることになります。

ところで、引数を借用にすべきかムーブにすべきかは、「必要がない限りはできるだけ借用にし、必要なときにだけムーブにする」という原則で考えるとよいでしょう。

というのも、引数を借用にしておけば、関数呼び出しが完了したら変数を元のスコープに返すことができますが、引数で所有権をムーブすると、基本的には所有権が返ってこないからです。関数に変数を渡しただけで以後その変数が使えなくなるのは不便ですよね。

この原則で考えると、文字列の足し算では少なくとも一方は借用で事足りそうです。たとえば足されるほうの文字列は、どんな文字列なのかを知りたいだけなので所有権までは欲しくないからです。

では、どちらか一方はムーブである必然性があるのでしょうか?

API ドキュメントにその理由が説明されています。 文字列の + は String の中で定義されています。

これによると、+ 演算で毎回新たな String をコピーしてメモリを確保すると効率が悪いため、渡された String を再利用して結合文字列を作るそうです。

それを行うために所有権のムーブが必要だというわけですね。

よって、+ 演算の一方がムーブで他方が借用である理由がわかりました。

最後に 「&str + String」 ではなく「String + &str」になっている理由ですが、これはおそらく String が文字列操作の標準ライブラリだから String 側に + 演算を実装したからだと思われます。

22
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
2