gpt4 book ai didi

rust - 如何从带有 &mut self 的方法中调用带有 self 的方法

转载 作者:行者123 更新时间:2023-12-05 03:34:02 25 4
gpt4 key购买 nike

我是 Rust 的新手,如果我做错了什么,我深表歉意。

我有一个 ConsoleApp 类,它包含一个 Worker 对象的向量。我希望每个 Worker 拥有一个线程并处理与之相关的所有事情。

但是,我在加入 Worker 持有的线程时遇到问题。

正如您在下面的代码中看到的,我有一个名为 run 的方法,它有一个对 self 的可变引用。

产生工作人员(更具体地说,工作人员的线程)工作正常,它需要对线程的可变引用。

问题在于 worker 的加入。当我调用 worker.join() 时,出现以下错误:

cannot move out of *worker which is behind a shared reference

move occurs because *worker has type models::worker::Worker, whichdoes not implement the Copy traitrustc(E0507)

我想我确实理解了这个问题:std::thread 中的 join 函数期望按值而不是按引用传递 JoinHandle .因此,我应该使 Worker 的连接函数也期望按值传递 self。但是,如果运行有 mut &self,我该怎么做?

控制台应用程序:

pub struct ConsoleApp {
accounts: Vec<Account>,
workers: Vec<Worker>,
}

impl ConsoleApp {
pub fn new() -> ConsoleApp {
return ConsoleApp {
accounts: initialize_accounts(),
workers: Vec::new()
}
}

pub fn run(&mut self) {
println!("Start console app.");
self.workers.iter_mut().for_each(|worker| worker.spawn());
self.workers.iter().for_each(|worker| worker.join());
println!("Stop console app.")
}
}

worker :

use std::thread;

pub struct Worker {
thread_join_handle: thread::JoinHandle<()>
}

impl Worker {
pub fn spawn(&mut self) {
self.thread_join_handle = thread::spawn(move || {
println!("Spawn worker");
});
}

pub fn join(self) {
self.thread_join_handle.join().expect("Couldn't join the associated threads.");
}
}

最佳答案

显而易见的方法是让 run() 也消耗 self。然后你可以这样写:

pub fn run(mut self) {
println!("Start console app.");
self.workers.iter_mut().for_each(|worker| worker.spawn());
self.workers.into_iter().for_each(|worker| worker.join());
println!("Stop console app.")
}

请注意 into_iter() 的使用,它在接管 vector 的内容时迭代 workers。当然,self.workers.into_iter() 不会编译成采用 &mut self 的方法。

如果修改 run() 以使用 self 是不可能的 - 例如,因为您希望允许 run()在同一 ConsoleApp 上多次调用 - 那么您可以使用 std::mem::take()&mut self 中提取 worker :

pub fn run(&mut self) {
println!("Start console app.");
self.workers.iter_mut().for_each(|worker| worker.spawn());
std::mem::take(&mut self.workers)
.into_iter()
.for_each(|worker| worker.join());
println!("Stop console app.")
}

std::mem::take(&mut self.workers)std::mem::replace(&mut self.workers, Vec::default ())。它会将值从引用中移出,并留下一个新的默认值作为其替代值。由于这只会移动指针而不移动向量的内容,并且由于不会分配空向量,因此该操作既高效又正确。

这种方法会有一个很好的副作用,即为 run() 的后续调用留空 self.workers。这是遵循借用检查器的结果之一 - 更好的代码。

关于rust - 如何从带有 &mut self 的方法中调用带有 self 的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70229148/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com