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 Hi…