Rust:文字列
Rust では文字列として取り扱われる型がいくつか存在している。
&str
プリミティブ型
文字列スライス
文字列の(部分的)参照。静的。変更不可。
原則、スタティック領域(メモリ上の固定領域)に配置される。
中身は&[u8] (u8型配列に対するスライス)
Copy トレイトを持ち、複数の変数に同時に設定できる。
String (alloc::string::String)
標準ライブラリによる型
動的。変更可。
ヒープ領域(メモリ上の動的確保された領域)に配置される。
中身は Vec<u8>
Vec<u8>
UTF-8 のバイト配列(動的)
&[u8]
UTF-8 のバイト配列(静的)
&str と String はなぜこの2種類が存在しているのか?
静的な文字列と動的な文字列の使い分けとして存在している。
文字列リテラルは &'static str 型になる。
ライフタイムがプログラムの開始から終了まで。
文字列リテラルはスタティック領域に配置されていて、それを参照する形。
&str 型は、str 型に対する参照という形だが、str 型を直接指定できるわけではない。
&str 型は原則外に持ち出せない。
原則として、持ち出すためには to_string() か to_owned() で String 型にする。
ライフタイムが 'static の場合にはそれを指定して外に持ち出せる。
std::any::type_name にはライフタイムが含まれていない。そもそもライフタイムはコンパイル時に解決されてしまって、実行時には見ることができない。
code:main.rs
fn type_name<T>(_: T) -> &'static str {
std::any::type_name::<T>()
}
fn main() {
let s = "Hello, world!";
println!("{}", s);
println!("{}", type_name(s));
println!("{}", type_name("Hello, world!"));
}
code:console
Hello, world!
&str
&str
関数の引数で受け取る場合
破壊的変更をするつもりがないなら、&str 型で受ける。
&String で受けてしまうと、&str から String に一度変換しなければならなくなるためよくない。
破壊的変更をするなら &mut String 型で受ける。
関数の出力で持ち出す場合
文字列リテラルの参照であることが明白なら &'static str 型で返す。
それ以外は String で返す。
分からない場合、&'static str で返してみて、エラーになったら String でもよさげ。
&str を String に変換する方法
これがよくまとまった記事になっている。4種類のトレイトに従い変換処理が存在している。
&str を String に変換する5つの方法
https://qiita.com/uasi/items/3b08a5ba81fede837531
String を &str に変換する方法
&を付ければ &str 型として参照可能になる。
その他の方法
[Rust] 文字列 String から文字列スライス str へ変換される仕組み
https://qiita.com/kerupani129/items/1d170d59720328d7a7c1
参考
&str を String に変換する5つの方法
https://qiita.com/uasi/items/3b08a5ba81fede837531