简体   繁体   English

rust 中 move 的语义是什么?

[英]What are the semantics of move in rust?

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();
            *num += 1;
            println!("Inner counter: {}", Arc::strong_count(&counter));
        });
        handles.push(handle);

        // println!("Inter counter: {}", Arc::strong_count(&counter));
    }

    println!("Outer counter: {}", Arc::strong_count(&counter));

    for handle in handles {
        handle.join().unwrap();
    }

    println!(
        "Result: {}, {}",
        *counter.lock().unwrap(),
        Arc::strong_count(&counter)
    );
}

Why can Inner counter and Outer counter output, but Inter counter will report an error?为什么Inner counterOuter counter都能输出,但是Inter counter会报错?

If I uncomment Inter counter , the rust compiler tells me:如果我取消注释Inter counter ,锈编译器会告诉我:

let counter: Arc<Mutex<i32>>
Go to Arc | Mutex

borrow of moved value: `counter`
value borrowed here after moverustcE0382
main.rs(10, 36): value moved into closure here
main.rs(11, 27): variable moved due to use in closure
main.rs(9, 13): move occurs because `counter` has type `Arc<Mutex<i32>>`, which does not implement the `Copy` trait

If counter has been moved inside the closure at theread::apawn , why can the outside still use it?如果counter已经在theread::apawn的闭包内移动了,为什么外面仍然可以使用它?

I'm not sure whether this is caused by the move keywords.我不确定这是否是由move关键字引起的。

If counter has been moved inside the closure at theread::apawn, why can the outside still use it?如果 counter 已经在 theread::apawn 的闭包内移动了,为什么外面仍然可以使用它?

Because you have two completely different variables with the name counter :因为您有两个名称为counter的完全不同的变量:

    let counter = Arc::new(Mutex::new(0));

and

        let counter = Arc::clone(&counter);

The second one gets move -d inside the closure, but the first one only gets borrowed during the iteration in order to clone it.第二个在闭包内得到move -d ,但第一个仅在迭代期间被借用以克隆它。

When the second counter gets created, it shadows the first one for the rest of the loop's body.当第二个计数器被创建时,它会为循环体的其余部分遮蔽第一个计数器。 So your code is semantically the same as:因此,您的代码在语义上与以下内容相同:

    for _ in 0..10 {
        let counter2 = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter2.lock().unwrap();
            *num += 1;
            println!("Inner counter: {}", Arc::strong_count(&counter2));
        });
        handles.push(handle);

        println!("Inter counter: {}", Arc::strong_count(&counter2));
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM