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

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

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

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

Q&A

解決済

2回答

678閲覧

Rustの借用の解除について

sundhy

総合スコア1

Rust

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

0グッド

0クリップ

投稿2023/11/02 06:35

編集2023/11/02 12:21

コンパイルエラーとなる例

Rust

1fn main() { 2 let mut x = 0; 3 let y = &mut x; 4 { 5 let z = y; 6 } 7 *y = 1; 8}

上記のコードでは、「y5行目で既にmoveされています」と出力されてしまいます

コンパイルエラーにならない例

Rust

1fn main() { 2 let mut x = 0; 3 let y = &mut x; 4 { 5 let z = &mut *y; 6 } 7 *y = 1; 8}

Rust

1fn func(z: &mut i32) {} 2 3fn main() { 4 let mut x = 0; 5 let y = &mut x; 6 func(y); 7 *y = 1; 8}

これらのコードでは問題なくコンパイルすることができるのですが、前者との違いは何なのでしょうか

説明が疎かになってしまい申し訳ございません

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

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

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

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

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

guest

回答2

0

ベストアンサー

型指定をしていないと所有権が移動したものとみなされます

Rust

1fn main(){ 2 let mut a=0; 3 let b=&mut a; 4 5 { 6 let c:&mut i32=b; //型指定あり 7 } 8 9 *b+=1; 10 println!("{}",b); 11}

Console

11

Rust

1fn main(){ 2 let mut a=0; 3 let b=&mut a; 4 5 { 6 let c=b; //型指定なし 7 } 8 9 *b+=1; 10 println!("{}",b); 11}

Console

1warning: unused variable: `c` 2 --> Main.rs:6:5 3 | 46 | let c=b; 5 | ^ help: if this is intentional, prefix it with an underscore: `_c` 6 | 7 = note: `#[warn(unused_variables)]` on by default 8 9error[E0382]: borrow of moved value: `b` 10 --> Main.rs:7:15 11 | 125 | let b=&mut a; 13 | - move occurs because `b` has type `&mut i32`, which does not implement the `Copy` trait 146 | let c=b; 15 | - value moved here 167 | println!("{}",*b); 17 | ^^ value borrowed here after move 18 | 19 = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info) 20 21error: aborting due to previous error; 1 warning emitted 22 23For more information about this error, try `rustc --explain E0382`. 24

関数の場合は必ず型宣言されるのでエラーにならないという理屈になりますね

型指定の有無で動作に差異が生じる理由は分かりません
詳しい方の解説に期待しましょう...

なお、

Rust

1let z = &mut *y;

この宣言を型宣言ありの形式で表すと

Rust

1let z:&mut i32=&mut *y;

となります

Rust

1let y:&mut i32=& mut x;

に相当するので通常の借用宣言と相違ないことが分かりますね

こちらも参考になるかもしれません
https://colorfulcompany.com/rust/borrow-reference

この質問を見て、以前にも検索結果に似たような内容があったのを思い出して調べたところ、ベストな質問がありました
こちらも参照の価値があるでしょう
https://teratail.com/questions/260892

投稿2023/11/02 12:07

編集2023/11/02 12:11
nanashi123

総合スコア51

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

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

sundhy

2023/11/02 12:28

ありがとうございます! コンパイラが`func(y)`や`let z: &mut i32 = y`の`y`を`&mut *y`として解釈してくれるということだったんですね!
guest

0

通常、変数の代入は所有権が移動するので、y の所有権が z に移動したため、それ以降は使えないですね

rust

1fn main() { 2 let mut x = "foo"; 3 let y = &mut x; 4 { 5 let _z = y; // yの所有権が移動 6 } 7 *y = "bar"; // 所有権が _z に移動したあと、y はもう使えないのでエラー 8 println!("{}", x); 9}

所有権ではなく参照を代入すれば、所有権は移動することがなくそれ以降も使えます。

rust

1fn main() { 2 let mut x = "foo"; 3 let y = &mut x; 4 { 5 let _z = &y; // 参照を代入すれば所有権は移動しない 6 } 7 *y = "bar"; // 所有権が移動していないため y は使える 8 println!("{}", x); 9}

また、掲示されている関数も「可変な参照」を受取るので所有権は移動しないですね

rust

1fn func(z: &mut i32) {} 2

より詳細な所有権の説明(通称rust book)はこちらを参照してみてください
https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html

投稿2023/11/02 10:55

gorilla0513

総合スコア128

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問