我有这样的事情:
use std::sync::Arc;
fn main() {
let arc = Arc::new(42);
move || { arc.clone() };
move || { arc.clone() };
}
Run Code Online (Sandbox Code Playgroud)
我正进入(状态:
error[E0382]: capture of moved value: `arc`
--> src/main.rs:6:19
|
5 | move || { arc.clone() };
| ------- value moved (into closure) here
6 | move || { arc.clone() };
| ^^^ value captured here after move
|
= note: move occurs because `arc` has type `std::sync::Arc<i32>`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)
我理解为什么我得到这个:clone之前没有被调用arc传递给闭包.我可以通过在函数中定义每个闭包并Arc在将其传递给闭包之前克隆它来解决这个问题,但还有另一种选择吗?
Vla*_*eev 14
没有其他办法了.您应该Arc在关闭之前克隆它.常见的模式是Arc在嵌套范围内将克隆重新绑定到相同的名称:
use std::sync::Arc;
fn main() {
let arc = Arc::new(42);
{
let arc = arc.clone();
move || { /* do something with arc */ };
}
{
let arc = arc.clone();
move || { /* do something else with arc */ };
}
}
Run Code Online (Sandbox Code Playgroud)
这通常与thread::spawn()以下一起完成:
use std::sync::{Arc, Mutex};
use std::thread;
const NUM_THREADS: usize = 4;
fn main() {
let arc = Arc::new(Mutex::new(42));
for _ in 0..NUM_THREADS {
let arc = arc.clone();
thread::spawn(move || {
let mut shared_data = arc.lock().unwrap();
*shared_data += 1;
});
}
}
Run Code Online (Sandbox Code Playgroud)
还有其他选择吗?
因为这种在定义闭包之前克隆事物的模式有些常见,所以有些人建议添加clone ||类似于move ||. 我不会对这种情况的发生抱有希望,但那里的一些评论指出宏可以很好地解决这个问题。
有几个板条箱提供了该宏的某种形式:
许多项目可能会定义自己的宏来执行类似的操作。例如,WASM 示例 rust-todomvc定义:
macro_rules! enclose {
( ($( $x:ident ),*) $y:expr ) => {
{
$(let $x = $x.clone();)*
$y
}
};
}
Run Code Online (Sandbox Code Playgroud)
可以用作:
fn main() {
let arc = Arc::new(42);
enclose! { (arc) move || arc };
enclose! { (arc) move || arc };
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
981 次 |
| 最近记录: |