文字リテラル Hello
から String
を作成し、一部を文字列スライスとして切り出した後、String
スコープ外で文字列スライスを使う。というシナリオを考えたが、以下のようにコンパイルエラーが発生する。文字列スライスが参照している大元の String
がスコープを抜ける際に Drop
してしまうためだ。
fn main() { let sub: &str; { let s = String::from("Hello"); sub = &s[0..2]; // ^ borrowed value does not live long enough } println!("{}", sub); // --- borrow later used here }
文字列スライスを clone()
すれば行けるか?と思ったが、文字列スライスは clone()
メソッドを実装していないようだ。同様に copy()
メソッドも実装されていなかった。
fn main() { let sub: &str; { let s = String::from("Hello"); sub = &s[0..2].clone(); // ^^^^^ method not found in `str` } println!("{}", sub); }
一度文字列スライスから String
を作成し、それを as_str()
で再度文字列スライス化しても、新たに生成した String
はスコープを抜ける際に Drop()
されてしまうので、同じだった。
fn main() { let sub: &str; { let s = String::from("Hello"); sub = String::from(&s[0..2]).as_str(); // ^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement // | // creates a temporary which is freed while still in use } println!("{}", sub); // --- borrow later used here }
文字列スライスを取得するのをあきらめて、文字列スライスを String
にしたものを取得するようにすると、コンパイルが通る。
fn main() { let sub: String; { let s = String::from("Hello"); sub = String::from(&s[0..2]); } println!("{}", sub); }
to_string()
のほうが String::from()
より簡潔に書けてよさそう。
fn main() { let sub: String; { let s = String::from("Hello"); sub = s[0..2].to_string(); } println!("{}", sub); }
というか、今回の例ではこれでもいいのか。簡潔に書きすぎて、いったい何がしたいんだ。。。というコードになるけど。。。
fn main() { let sub: String; { sub = "Hello"[0..2].to_string(); } println!("{}", sub); }