reference - 返回不可变引用后面的可变引用,传递给函数
问题描述
如何返回一个位于不可变引用后面的可变引用,作为参数传递给函数,如何处理?
struct Foo { i: i32 }
struct Bar<'b> {
f: &'b mut Foo
}
impl<'a: 'b, 'b> Bar<'b> {
fn func(&'a self) -> &'b mut Foo {
self.f
}
}
fn main() {
let mut foo = Foo { i: 1 };
let bar = Bar { f: &mut foo };
bar.func();
}
给出以下错误:
error[E0389]: cannot borrow data mutably in a `&` reference
--> src/main.rs:9:14
|
8 | fn func(&'a self) -> &'b mut Foo {
| -------- use `&'a mut self` here to make mutable
9 | self.f
| ^^^^^^ assignment into an immutable reference
我(有点)理解编译器在这里试图阻止什么。但我对错误消息感到困惑assignment into an immutable reference
。究竟是什么被分配到self
(或内部self.f
?)?
我写了下面的代码来模拟这个问题,得到了同样的错误信息,与上面的不同,我能够理解。这是代码:
fn main() {
let mut foo = Foo { i: 1 };
let bar = Bar { f: &mut foo };
let pbar = &bar;
pbar.f.i = 2; // assignment into an immutable reference
}
在第一个示例中,它是否试图将可变引用f
移出self
(因为&mut
不是Copy
类型),将其视为不可变引用内部的突变self
,因此出现错误消息assignment into an immutable reference
?
解决方案
您不能从不可变引用创建可变引用。这意味着您需要更改&self
为&mut self
:
impl<'a: 'b, 'b> Bar<'b> {
fn func(&'a mut self) -> &'b mut Foo {
self.f
}
}
现在您的变量需要是可变的,以便您可以为方法获取可变引用:
let mut bar = Bar { f: &mut foo };
bar.func();
究竟是什么被分配给自我(或内部
self.x
?)?
错误消息可能有点不对劲。您的代码中没有赋值,但您返回的是一个可变引用。可变引用允许您在这里做的唯一额外的事情是分配self.f
or self.f.i
。
绝对可以改进此错误消息,但它确实包含使&'a self
可变以解决问题的提示。
现在,你原来的问题:
如何返回一个位于不可变引用后面的可变引用,作为参数传递给函数,如何处理?
Rust 为内部可变性提供了多种容器类型,例如Cell
和RefCell
. 这些类型负责确保远离编译器的正确性并使其成为运行时检查。将 aRefCell
应用于您的代码的一种方法可能是这样的:
use std::cell::RefCell;
use std::ops::DerefMut;
struct Foo { i: i32 }
struct Bar<'b> {
// store the data in a RefCell for interior mutability
f: &'b RefCell<Foo>
}
impl<'a: 'b, 'b> Bar<'b> {
// Return a RefMut smart pointer instead of mutable ref, but hide the implementation,
// just exposing it as something that can be mutably dereferenced as a Foo
fn func(&'a self) -> impl DerefMut<Target = Foo> + 'b {
self.f.borrow_mut()
}
}
fn main() {
let foo = RefCell::new(Foo { i: 1 });
let bar = Bar { f: &foo };
let mut f = bar.func();
f.i = 3;
}
推荐阅读
- python - 在 docker 中安装 requirements.txt - 网络问题
- nopcommerce - NopCommerce 缺少参考插件
- json - 邮递员测试 Web API 以获取 oauth 令牌。但总是得到 400 BAD REQUEST 响应
- postgresql - Postgres 复制槽显示不活动
- c++ - Qt 和 Qwt 在 ubuntu 18.04 下部署
- f# - 负载平衡请求/农场请求(并发和状态 - 尴尬)
- python - 如何真正过滤 pandas 数据集而不让 Nans 无处不在
- python - 如何使用 Selenium 和 Python 查找从 covid 中恢复的人数的类路径
- python - 如何获取日志模块中日志记录的列号?
- flutter - 使用 dart 的非对称 zip 文件加密