[英]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 counter
和Outer 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.