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

标签 rust

我是 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, which does 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/

相关文章:

python - PyO3 中自定义结构的向量

rust - 如何将 std::fmt::Arguments 转换为字符串?

rust - 优化级别 `-Os` 和 `-Oz` 在 rustc 中有什么作用?

rust - 将类型注释添加到 "the ` 时出现 ` method cannot be invoked on a trait object"and_then `and_then` 错误

unix - 有没有办法在 Unix 平台上使用 Rust 更改文件元数据(例如所有者)?

rust - "cannot find macro"宏自身doc测试错误

c - Rust ffi + wasm (yew -> cargo 网络启动) -> fatal error : 'math.h' file not found

rust - 收集到 rust 中拥有的字符串的拥有的 vec

rust - 在没有转变的情况下为拥有的奶牛重用向量堆空间?

arrays - 数组向量的内存布局是什么?