【问题标题】:How do I get a mutable reference out of a vector?如何从向量中获取可变引用?
【发布时间】:2022-01-07 02:25:09
【问题描述】:

runsend 方法都需要 self 对象,send 函数还需要可变的 Packet 引用:

struct Package {
    id: u32,
}

impl Package {
    fn new(id: u32) -> Package {
        Package { id }
    }
}

struct Manager {
    packages: Vec<Package>,
}

impl Manager {
    fn new() -> Manager {
        Manager {
            packages: vec![
                Package::new(1),
                Package::new(2),
                Package::new(3),
                Package::new(4),
            ],
        }
    }
    fn run(&mut self) {
        for package in self.packages.iter_mut() {
            if package.id == 1 {
                self.send(package);
            }
            println!("{}", package.id);
        }
    }
    fn send(&self, package: &mut Package) {
        package.id = 23;
    }
}

fn main() {
    let manager = Manager::new();
    manager.run();
}
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src/main.rs:29:17
   |
27 |         for package in self.packages.iter_mut() {
   |                        ------------------------
   |                        |
   |                        mutable borrow occurs here
   |                        mutable borrow later used here
28 |             if package.id == 1 {
29 |                 self.send(package);
   |                 ^^^^ immutable borrow occurs here

error[E0596]: cannot borrow `manager` as mutable, as it is not declared as mutable
  --> src/main.rs:41:5
   |
40 |     let manager = Manager::new();
   |         ------- help: consider changing this to be mutable: `mut manager`
41 |     manager.run();
   |     ^^^^^^^ cannot borrow as mutable

如何重构这两个函数以使其正常工作?

我不想复制数据包,因为这会给我的原始代码带来很多麻烦。

【问题讨论】:

    标签: rust reference self borrow-checker


    【解决方案1】:

    选项 1:不要在 send() 中接受 &amp;self。让它从self 中取出它需要的东西,比如&amp;mut Package 和可能的其他字段:

    // call it with Self::send(package)
    fn send(package: &mut Package) {
        package.id = 23;
    }
    

    选项 2:接受包索引而不是 &amp;mut Package

    fn run(&mut self) {
        for package_idx in 0..self.packages.len() {
            if self.packages[package_idx].id == 1 {
                self.send(package_idx);
            }
            println!("{}", self.packages[package_idx].id);
        }
    }
    
    fn send(&mut self, package_idx: usize) {
        self.packages[package_idx].id = 23;
    }
    

    选项 3:使用内部可变性。

    struct Manager {
        packages: Vec<RefCell<Package>>,
    }
    
    impl Manager {
        fn new() -> Manager { ... }
    
        fn run(&mut self) {
            for package in &self.packages {
                if package.borrow().id == 1 {
                    self.send(package);
                }
                println!("{}", package.borrow().id);
            }
        }
        fn send(&self, package: &RefCell<Package>) {
            let package = package.borrow_mut();
            package.id = 23;
        }
    }
    

    哪个选项适合您取决于您​​的用例。在其他条件相同的情况下,我更喜欢选项 1,然后是 2,然后是 3。

    【讨论】:

    • 尽管我认为 1 是最好的,但我的用例需要一个 self 对象。所以我选择 3。
    猜你喜欢
    • 1970-01-01
    • 2022-01-10
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多