rust: &str と String を分かって使い分けたい
2025/11/03
Rust で固定文字列を使うことがある。
そのとき、"ほにゃほにゃ" と書いて、vscode で波線が出てきたら .to_string() を付けている。
関数の引数にするときは &str を使ってよいかよくわからないので考えずに &String を使っている。
これはよろしくなかろう。
プリミティブ型
&str も String も std 関係だ。
std はクレートで、その中にプリミティブ型がある。
クレートごとにプリミティブ型を実装できるのだろうか? あまりそういう気はしないのだが。
ChatGPT 氏に訊くと、プリミティブ型が定義されているのではなく再エクスポートしているだけだそうだ。
ドキュメントの都合と思っておけばよさそう。
Rust の文字列
str はプリミティブ型の文字列スライス。
その借用が &str。
固定文字列の "ほにゃほにゃ" は &str というガイド表示が出てくる(vscode)のでそうなのだろう。
str 単独では使えなかったと思う。str::from_utf8() のような使い方はあるようだ。
String は std::string の一員だ。
str ページの URL が std/primitive.str.html こちらは std/string/struct.String.html なので構造体と思っておけば良いか。
中身 はこれだけだ。
pub struct String {
    vec: Vec<u8>,
}
固定文字列
strの説明 からすると、固定文字列(string literal)を明示的に書くと &'static str とのこと。
ライフタイムがプログラム全体という意味らしい。
プログラムに直接埋め込まれていてずっと有効というだけだろう。
明示的に書かなくても固定文字列であることに変わりは無いので、変数が見えるならプログラム全体でいつでも有効ということになる。
str ではなく &str なのも、貸し借りできないというか、動かすことができない常に借用されたデータとしてしか使用できないという意味なのだと思う。
ただ 'static は「プログラムで固定」の意味が強そうだ。
Deref
String には Deref<Target = str> というものがある。
しかし String::Deref の説明に出てくるコードのどこが参照外しなのだろう。
fn takes_str(s: &str) { }
let s = String::from("Hello");
takes_str(&s);
String から &str のように構造体(スマートポインタ?)を参照で扱うのも Deref なのだろう。
これがあるから &str なのか String なのかだんだんわからなくなってくるのだと思う。
これがないと &str から String にできるのにその逆がないので面倒なことになりそう。。。
と思ったが、.as_str() を呼び出しているだけなのか。
impl ops::Deref for String {
    type Target = str;
    #[inline]
    fn deref(&self) -> &str {
        self.as_str()
    }
}