🤝

Rust における文字列の所有権

2024/05/26に公開

はじめに

Rust で参照&を利用するシーンは少なくないことですよね。
個人的に、Rust の学習において、所有権、所有権解放、メモリ等は理解しておかなければいけないところかなと感じています。

今回は文字列にフォーカスして、紹介していけたらと思います。

文字列

参照はすでに知っている方もいらっしゃる方も少なくないかもしれません。
&を付けることによって、所有権を保持することのない参照の値とすることができます。

fn main() {
    let name = "Rust".to_string();
    let rename = &name;

    println!("{}", name);
    println!("{}", rename)
}

逆に、&をつけない場合は、コンパイルエラーとなります。

fn main() {
    let name = "Rust".to_string();
    let rename = name;

    println!("{}", name);
    println!("{}", rename)
}
borrow of moved value: `name`
value borrowed here after move

これは、所有権のムーブによって起きるコンパイルエラーです。
rename変数の生成時に、nameは所有権を失うため、println!にてエラーが起きてしまいます。

以下のような場合でも、コンパイルエラーとなります。

fn main() {
    let name = "Rust".to_string();

    print_intro(name);

    println!("{}", name);
}

fn print_intro(name: String) {
    println!("Welcome to the world of {}", name);
}

これも、所有権のムーブが発生しているため、main関数の最終行、println!でコンパイルエラーとなります。

文字列スライス

続いて、スライス文字列はどうなるでしょうか。
スライス文字列は所有権の持たないデータ型です。
&strという型で表現されます。

fn main() {
    let name = "Rust";
    let rename = name;

    println!("{}", name);
    println!("{}", rename)
}

上記の例では、コンパイルエラーが起きません。
スライス文字列は宣言時にすでに & がついているため rename変数宣言時にも &をつける必要はありません。

以下のように、関数の引数に追加した場合も同様に、コンパイルエラーが起きません。

fn main() {
    let name = "Rust";

    print_intro(name);

    println!("{}", name);
}

fn print_intro(name: &str) {
    println!("Welcome to the world of {}", name);
}

おわりに

文字列と、文字列スライスの所有権周りの挙動の違いを見てみました。
より Rust を使いこなせるようになるため、今後もこの辺りの学習に精を出していきたいと思います!

では。

コラボスタイル Developers

Discussion