rust - 如何告诉编译器在不删除整个结构的情况下释放结构中的借用?
问题描述
我有以下结构,它表示数字计算的计划:
pub struct NfftPlan<'a> {
x: Option<&'a [f64]>,
f_hat: Option<&'a [Complex64]>,
// ...
}
它有一个set_f_hat
方法:
pub fn set_f_hat(&mut self, f_hat: &'a [Complex64]) {
self.f_hat = Some(f_hat);
}
和一个execute
方法:
pub fn execute(&self) -> Vec<Complex64>
它使用f_hat
不变。
我想通过以下方式使用它:
let mut f_hat = vec![1,2,3,4];
let plan = NfftPlan::new()
plan.set_f_hat(&f_hat);
plan.execute();
f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation
f_hat
这失败了,因为我在plan
仍然存在时无法变异。有没有办法plan
释放f_hat
允许我改变f_hat
向量的借用?像这样的东西:
releasedata(&self) {
self.f_hat = None
} //Now the compiler forgets that plan would hold an borrow to f_hat
我知道 Rust 不允许我在存在借用时更改向量,在这种情况下是通过结构f_hat
中的引用NfftPlan
。我想要一种方法来告诉编译器在NfftPlan
不删除整个结构的情况下删除对结构中向量的引用。
解决方案
解释
我如何告诉编译器释放借用
你不能,期间。这不是你“告诉”编译器的事情,编译器知道一切。您只能完全停止使用该参考。
不删除整个结构
Dropping不会清除借用,只有不再使用的借用才会清除,这可能发生在 drop 中。
f_hat[0] = 3; // Change f_hat to a new value plan.execute(); //New computation
这正是Rust 试图阻止的代码类型之一。应该返回不同的值一点也不明显,plan.execute()
因为一些明显不相关的值已经改变。
解决方案
在类型系统中对其进行编码
我会构建我的类型以反映它们需要如何使用,创建一次性值,这些值只有在所有内容组合在一起后才能执行。这意味着借用的结构f_mut
一旦完成就会被删除;请注意这如何Option
完全删除:
fn main() {
let mut f_hat = 42;
let plan = Plan::default();
plan.set_f_hat(&f_hat).execute();
f_hat = 3;
plan.set_f_hat(&f_hat).execute();
}
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
}
impl<'a> Plan<'a> {
fn set_f_hat(&self, f_hat: &'a i32) -> PlanPlus<'a> {
PlanPlus { x: self.x, f_hat }
}
}
#[derive(Debug)]
struct PlanPlus<'a> {
x: Option<&'a i32>,
f_hat: &'a i32,
}
impl<'a> PlanPlus<'a> {
fn execute(&self) {}
}
使用内部可变性和引用计数
use std::{cell::Cell, rc::Rc};
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
f_hat: Option<Rc<Cell<i32>>>,
}
impl<'a> Plan<'a> {
fn set_f_hat(&mut self, f_hat: Rc<Cell<i32>>) {
self.f_hat = Some(f_hat);
}
fn execute(&self) {}
}
fn main() {
let f_hat = Rc::new(Cell::new(42));
let mut plan = Plan::default();
plan.set_f_hat(f_hat.clone());
plan.execute();
f_hat.set(3);
plan.execute();
}
认识到成员是可变的
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
f_hat: Option<&'a mut i32>,
}
impl<'a> Plan<'a> {
fn f_hat(&mut self) -> &mut Option<&'a mut i32> {
&mut self.f_hat
}
fn execute(&self) {}
}
fn main() {
let mut f_hat = 42;
let mut plan = Plan::default();
*plan.f_hat() = Some(&mut f_hat);
plan.execute();
**plan.f_hat().as_mut().unwrap() = 3;
plan.execute();
}
也可以看看:
推荐阅读
- amazon-web-services - 试图将所有流量从 EC2 重定向到容器
- c++ - 在一个程序中使用具有内部和外部链接的变量名
- json - Swift UI 获取 JSON
- java - 在 android studio 中从 Uri 获取路径文件
- java - bean初始化-我收到AssertionError:尚未实现
- lisp - 格式化长字符串的奇怪行为
- python - 根据python中列的标签创建groupby
- vue.js - Vue Router如何加载第二个组件加载
- azure-devops - 浏览器堆栈配置任务 Azure 管道中的 URI 无效
- android - 如何在共享首选项中保存数据类型“整数”(可为空的 int)