「TAURI」を使う前に、まず「Rust」の所有権を理解する

2023年11月2日(木)
大西 武 (オオニシ タケシ)
第4回の今回は、「TAURI」をプログラミングしていく前に「Rust」で最も重要な「変数」に与えられる「所有権」について解説します。

所有権の「コピー」について

Rustでは変数に所有権がありますが、先述の通り「数値」を代入した変数は「コピー」されるので所有権を気にする必要はありません。例えば、図3とサンプルコードのように数値を代入した変数を書けばエラーが出ません。

数値のコピーは複数のデータを持つ必要がなく、アドレスを持つことと同じ1個だけの型の変数を持てば良いので、ムーブしても所有権の概念は必要ないからです。

図3:所有権の「コピー」

・所有権のコピーのサンプルコード
fn main() {
    let good1 = 0;
    let good2 = good1;
    println!("{}",good1); // エラーなし
    println!("{}",good2); // エラーなし
}

【サンプルコードの解説】
「good1」変数に数値「0」を代入して宣言します。
「good2」変数に「good1」変数をコピーします。
「good1」変数をターミナルに表示します。
「good2」変数をターミナルに表示します。

所有権と「関数」について

変数を関数の引数に渡しても所有権のムーブが起こります。すると図4とサンプルコードのようにムーブした元の「good1」変数にはもう所有権が残っていないため、「good1」変数を使おうとするとエラーが起こります。

このエラーを回避するには「先述と同じclone()関数でクローンするように」とターミナルにエラーメッセージが出ます。次のサンプルコードでエラーを回避するには「good_str(good1);)」→「good_str(good1.clone());」と書き換えクローンを使います。

図4:所有権と「関数」

・所有権と関数のサンプルコード
fn main() {
    let good1 = String::from("Good");
    good_str(good1); // → good_str(good1.clone());
    println!("{}",good1); //エラー
}

fn good_str(_good: String) {
}

【サンプルコードの解説】
「good1」変数に"Good"を代入して宣言します。
「good_str」関数にgood1を引数として渡します。「_good」引数の最初に「_(アンダーバー)」が付いているのは、関数内でこの引数を使わないことを表しています。
ターミナルにgood1の文字列を表示しようとするとエラーが出ます。

所有権と「関数の戻り値」について

関数内の変数から所有権をムーブするには、図5とサンプルコードのように「good_str」関数内で宣言された変数の所有権を「戻り値」で受け取れば「good1」変数に所有権が渡ります。

ところで、例えば「good_str」関数の戻り値の書式は、関数の最後で「;」なしの「good」か、一般の他のプログラミング言語と同じく「return good;」のように書きます。

図5:所有権と「関数の戻り値」

・所有権と関数の戻り値のサンプルコード
fn main() {
    let good1 = good_str();
    println!("{}",good1); // エラーなし
}

fn good_str() -> String {
    let good = String::from("Good");
    good
}

【サンプルコードの解説】
「good_str」関数で「good」変数に"Good"文字列を代入し、戻り値「good」を「good1」変数に代入します。
「good1」変数をターミナルに表示します。

所有権と「関数の引数と戻り値」について

関数に引数を渡してもクローンを使わずにムーブだけで元の変数「good1」を使えるようにするには、図6とサンプルコードのように「good1」引数をmut(変数の値を変更可能)にして関数に渡した引数を「戻り値」で受け取るようにします。

なお「good_str」関数から渡した「good1」引数の所有権を「戻り値」で受け取れば、再度「good1」変数に所有権が返ります。

図6:所有権と「関数の引数と戻り値」

・所有権と関数の引数・戻り値のサンプルコード
fn main() {
    let mut good1 = String::from("Good");
    good1 = good_str(good1);
    println!("{}",good1); // エラーなし
}

fn good_str(good: String) -> String {
    return good;
}

【サンプルコードの解説】
「good1」変数に"Good"を代入してmutでミュータブルに宣言します。
「good_str」関数の引数にgood1変数を渡し、戻り値をgood1変数に代入します。
「good1」変数をターミナルに表示します。

著者
大西 武 (オオニシ タケシ)
1975年香川県生まれ。大阪大学経済学部経営学科中退。プログラミング入門書など30冊以上を商業出版。Microsoftで大賞やNTTドコモでグランプリなど20回以上全国区のコンテストに入賞。オリジナルの間違い探し「3Dクイズ」が全国放送のTVで約10回出題。

連載バックナンバー

開発言語技術解説
第15回

「TAURI」でデータベースを使ってみよう

2024/5/10
第15回の今回は「TAURI」でオープンソースのデータベース「SQLite3」を使用して、テーブル表に表示する解説をしていきます。
開発言語技術解説
第14回

「TAURI」で気象庁の「CSVデータ」を解析する

2024/5/1
第14回の今回は気象庁のWebサイトから指定した地域の1年間の気象データをダウンロードして「TAURI」で解析していきます。
開発言語技術解説
第13回

「TAURI」で「簡易RSSリーダー」を開発してみよう

2024/4/16
第13回の今回は「TAURI」で「RSSフィード」を読み込んでWebページに一覧表示し、リンクのページを開くための新規ウィンドウを作成するところまでを解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています