rust - 内部 Rust 结构可以传递对其所有者的引用吗?
问题描述
从副本中,@Shepmaster 在此答案中记录了一组真正出色的解决此问题的模式。谢谢你
Account
Bank
调用方法时需要访问的字段。Bank
有deposit()
调用set()
帐户,但set()
需要了解有关银行的信息,因此必须将银行传递到Account::set
. 我确信有其他方法可以解决这个问题,这在 Rust 中更有意义。我很难找到更好的替代模式来替代我会用其他语言做的事情。
这是一个来自Twitch 流的最小示例,我尝试在 Rust 中创建一个简单的流行病学模型——如果我理解了,我将在下一个中给出答案。
fn main() {
// create a bank and fill with accounts:
let mut bank = Bank { accounts: vec![] };
for i in 0..100 {
bank.accounts.push(Account {
id: i,
balance: 0,
mean_deviation: 0,
});
}
// set the balance of an account
bank.deposit(42, 10000);
}
// BANK:
struct Bank {
accounts: Vec<Account>,
}
impl Bank {
pub fn deposit(&mut self, id: usize, balance: i32) {
let account = self.accounts.get_mut(id).unwrap();
// this fails, because account needs access to information from the bank struct,
// and we cannot borrow bank as mutable twice, or immutable when already mutable:
account.set(balance, self);
}
}
// ACCOUNT:
struct Account {
id: i32,
balance: i32,
mean_deviation: i32,
}
impl Account {
pub fn set(&mut self, balance: i32, bank: &Bank) {
self.balance = balance;
/* use bank to calculate how far from the mean account value this account is */
}
}
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/main.rs:27:30
|
23 | let account = self.accounts.get_mut(id).unwrap();
| ------------- mutable borrow occurs here
...
27 | account.set(balance, self);
| --- ^^^^ immutable borrow occurs here
| |
| mutable borrow later used by call
解决方案
老实说,最好的方法是尽可能避免它。循环引用一点都不好。
这是另一种思考方式:通过使用Cell
包装帐户余额的 a ,您可以根据需要读取/写入新值。
use std::cell::Cell;
fn main() {
// create a bank and fill with accounts:
let mut bank = Bank { accounts: vec![] };
for i in 0..100 {
bank.accounts.push(Account {
id: i,
balance: Cell::new(0),
mean_deviation: Cell::new(0),
});
}
// set the balance of an account
bank.deposit(42, 10000);
}
// BANK:
struct Bank {
accounts: Vec<Account>,
}
impl Bank {
pub fn deposit(&self, id: usize, balance: i32) {
let account = self.accounts.get(id).unwrap();
account.set(balance, &self);
}
}
// ACCOUNT:
struct Account {
id: i32,
balance: Cell<i32>,
mean_deviation: Cell<i32>,
}
impl Account {
pub fn set(&self, balance: i32, bank: &Bank) {
let old_balance = self.balance.get();
self.balance.set(old_balance + balance);
/* use bank to calculate how far from the mean account value this account is */
let _ = bank.accounts.len();
}
}
如果出于某种原因您愿意在多线程中使用它,则应该将atomic
类型用于简单的原语。
推荐阅读
- docker - 打开容器cli时docker执行命令
- excel - 如何使用 Range(cells..) 而不是 range("A1...) 清除内容
- python - PyOpenGL如何通过VBO为元素着色
- java - 使用 vs 代码将外部库添加到 Spring Boot 应用程序
- typescript - 推断 Typescript 中两个参数的基本类型
- powershell - 如何在 PS 脚本中添加 URL 名称而不是编号
- django - 403 禁止 - Apache2
- power-automate - 使用 Office 365 E3 许可证在 Power 中使用高级连接器自动化
- r - 当地块纵横比为 1 时将地块与拼凑组合
- java - Spring Boot 参照完整性约束违反仅在管道中的服务器上