その他

【Rust】文字列について

その他
この記事は約3分で読めます。

2種類の文字列

Rustには主要な文字列型が二種類あります。&str と Stringです。

  • String: ヒープ領域に保存される文字列(伸張可能・UTF-8)
  • &str: 文字列スライス(固定サイズで変更不可能・UTF-8のバイトシーケンスへの参照)

文字列を読むだけなら参照で十分

let string = String::from("127.0.0.1:8080");
let string_slice = &string[10..];

dbg!(&string);
dbg!(string_slice);

// &string = "127.0.0.1:8080"
// string_slice = "8080"

&strは、最初に&がついていることからもわかるように、参照です。

例えば単純に文字列をコピーする場合、Stringを使用すると再度ヒープに割り当てられます。
これはメモリがもったいない。参照だけなら&strで、所有権の移動もありません。

従って上記の例だと、以下のようになります。

// ヒープに格納された文字列
let string = String::from("127.0.0.1:8080");

// ヒープに格納されたstringを参照するのみ
let string_slice = &string[10..];

文字列を変更する場合

反対に、文字列に破壊的な変更を加える場合はStringの使用が必要です。

何をスライスしているのか

let string_slice = &string[10..];

1文字 = 1バイトとは限りません。JSなど高級言語に慣れた私には、10文字目以降を参照しているように見えますが違います。日本語や絵文字など2バイト以上の文字を参照すると、クラッシュする場合もあります。

このことから、参照が見ている(?)のはあくまでメモリ領域にのバイト列であることがわかります。
ヒープにある文字列の、あるバイトをポインタしているのです。
また、文字列スライスは文字列の長さの情報も持ちますので、先頭のバイトがわかれば後に続く文字列全体を確定できます。

まとめ

  • String: ヒープ領域に保存される文字列(伸張可能・UTF-8)
    • UTF-8 バイト列(先頭?)へのポインタ
    • 列の長さ
    • キャパシティ(これを超えるとさらに大きな領域が割り当てられる)
  • &str: 文字列スライス(固定サイズで変更不可能・UTF-8のバイトシーケンスへの参照)
    • ヒープに格納された UTF-8文字列のアドレス
    • 列の長さ

参考

[Rust] &strとStringを理解しようと思ったらsliceやmutを理解できてないことに気づいた話 - Qiita
Rust入門メモ。 Rustは文字列を表す型として &str と String がある これが、結構ややこしくて、どういうときにどっちを使うべきなのかがよくわからない 環境 OS: macOS High Sierra ...