質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

6116閲覧

Rustでクロージャの左に置かれているmoveはなんですか?

tasuren

総合スコア76

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2022/01/10 01:35

私は今Rustの勉強をしています。
最近私が見たコードの以下のコードのmoveが何をしているのかわかりません。

rust

1//! 元:https://qiita.com/takayahilton/items/ebc19d72a8004fb8e233 2 3#![feature(conservative_impl_trait)] 4 5fn count(n: u32) -> impl FnMut() -> u32 { 6 let mut num = n; 7 move || {num += 1; num} // >> ここの`move`です。 << 8} 9 10fn main() { 11 let mut counter = count(0); 12 println!("{}", counter()); //1 13 println!("{}", counter()); //2 14 println!("{}", counter()); //3 15}

調べても所有権の移動についての記事等がでるだけで文であるmoveがなんなのかがでてきませんでした。
誰か教えて欲しいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

それはクロージャに捕捉した変数の所有権を移すための構文です。
クロージャは関数の外にある変数を捕捉しますが、デフォルトでは捕捉するときに参照で捕捉します。これを所有権ごと捕捉するようにするのが move || {} 構文です。ドキュメントだとクロージャの章で触れられています。

クロージャ:環境をキャプチャできる匿名関数 - The Rust Programming Language 日本語版

ドキュメントでの説明が簡素すぎるので以下に補足します。

move をつける/つけないで挙動が変わるコード例が以下になります。変数を捕捉して書き換えるクロージャを書いて呼び出したあとに、捕捉された変数が書き換えの影響を受けるか受けないかが変わります。

rust

1// moveしないクロージャ 2let mut num = 0; 3let mut ref_cls = || { 4 num += 1; 5 num 6}; 7assert_eq!(ref_cls(), 1); 8// numはクロージャと共有されてるので変更される 9assert_eq!(num, 1);

rust

1// moveするクロージャ 2let mut num = 0; 3// 本当は所有権がムーブするが、数値はCopyな型なのでコピーされる 4let mut ref_cls = move || { 5 num += 1; 6 num 7}; 8assert_eq!(ref_cls(), 1); 9// numはクロージャとは無関係になったので影響を受けない 10assert_eq!(num, 0);

他にも、もちろん借用と所有権の移動の違いがあるので捕捉された変数をクロージャを作ったあとに使えるかも変わります。

rust

1// moveしないクロージャ 2let s = "String".to_string(); 3let ref_cls = || { 4 println!("{}", s); 5}; 6// 借用してるので使える 7println!("{}", s);

rust

1// moveするクロージャ 2let s = "String".to_string(); 3let ref_cls = move || { 4 println!("{}", s); 5}; 6// `s`は既にムーブしているので使うとエラー 7// println!("{}", s);

質問のコードは move を外すと動かなくなると思います。 num を借用していると関数の終わりでライフタイムが尽きるので関数の外に持ち出せなくなるからです。

投稿2022/01/10 06:24

blackenedgold

総合スコア468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tasuren

2022/01/11 03:51

なるほど、ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問