如何从向量中获取可变引用?
How do I get a mutable reference out of a vector?
run
和send
方法都需要一个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
如何重构这两个函数以使其正常工作?
我不想复制数据包,因为那样会给我的原始代码带来很多麻烦。
选项 1:不接受 send()
中的 &self
。让它从 self
中获取它需要的东西,例如 &mut Package
和可能的其他字段:
// call it with Self::send(package)
fn send(package: &mut Package) {
package.id = 23;
}
选项 2:接受包索引而不是 &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。
run
和send
方法都需要一个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
如何重构这两个函数以使其正常工作?
我不想复制数据包,因为那样会给我的原始代码带来很多麻烦。
选项 1:不接受 send()
中的 &self
。让它从 self
中获取它需要的东西,例如 &mut Package
和可能的其他字段:
// call it with Self::send(package)
fn send(package: &mut Package) {
package.id = 23;
}
选项 2:接受包索引而不是 &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。