2

次のコードはコンパイルに失敗します。

use std::thread;

#[derive(Debug)]
struct Contained {
    a: u8
}

#[derive(Debug)]
struct Wrapper<'a> {
    b: &'a Contained,
}

fn main() {
    println!("Hello, world!");

    let c = Contained { a: 42 };
    let w = Wrapper { b: &c };

    println!("C: {:?}", c);
    println!("W: {:?}", w);

    let handle = thread::spawn(move || {
        println!("C in thread: {:?}", c);
    });
    handle.join().unwrap();
}

エラーメッセージ:

src/main.rs:24:39: 24:40 error: cannot move `c` into closure because it is borrowed [E0504]
src/main.rs:24         println!("C in thread: {:?}", c);
                                                     ^
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:24:9: 24:42 note: in this expansion of println! (defined in <std macros>)
src/main.rs:18:27: 18:28 note: borrow of `c` occurs here
src/main.rs:18     let w = Wrapper { b: &c };
                                         ^

これについては、借用チェッカーは明らかに正しいです。これを回避する方法は、明示的なスコープを使用することです。これにより、ラッパーが削除され、借用された含まれているオブジェクトが解放されます。

let c = Contained { a: 42 };
{
    let w = Wrapper { b: &c };
    println!("C: {:?}", c);
    println!("W: {:?}", w);
}
let handle = thread::spawn(move || {
    println!("C in thread: {:?}", c);
});

これは正しくコンパイルされます。

オブジェクトをスコープ外にするもう 1 つの方法は、std::mem::drop関数を使用することです。ただし、この場合は機能しません。

let c = Contained { a: 42 };
let w = Wrapper { b: &c };
println!("C: {:?}", c);
println!("W: {:?}", w);
drop(w);
let handle = thread::spawn(move || {
    println!("C in thread: {:?}", c);
});

ボロー チェッカーは、以前と同じエラー メッセージを表示します。

drop(w)借りたものを解放しないのはなぜcですか?

4

0 に答える 0