rust - “不能返回引用临时值的值”和 Rust 中的内部可变性
问题描述
我在 Rust 中有以下代码:
pub struct RegExpFilter {
...
regexp_data: RefCell<Option<RegexpData>>,
...
}
struct RegexpData {
regexp: regex::Regex,
string: String
}
...
pub fn is_regexp_compiled(&self) -> bool {
self.regexp_data.borrow().is_some()
}
pub fn compile_regexp(&self) -> RegexpData {
...
}
fn regexp(&self) -> ®ex::Regex {
if !self.is_regexp_compiled() { // lazy computation that mutates the struct
self.regexp_data.replace(Some(self.compile_regexp()));
}
&self.regexp_data.borrow().as_ref().unwrap().regexp
}
pub fn matches(&self, location: &str) -> bool {
self.regexp().find(location)
}
regexp 是惰性计算的,因此使用捕获&mut self
i 不想要RefCell
的。
我收到以下消息:
&self.regexp_data.borrow().as_ref().unwrap().regexp
| ^-------------------------^^^^^^^^^^^^^^^^^^^^^^^^^
| ||
| |temporary value created here
| returns a value referencing data owned by the current function
编译器消息似乎很清楚:Ref
由borrow()
外部临时创建并返回。但是我相信Option
( self.regexp_data
) 归RefCell
结构本身所有,因此在内部使用它应该没问题(因为函数不是pub
)。
我还尝试了以下方法(但失败并显示相同的消息)
fn regexp(&self) -> impl Deref<Target = regex::Regex> + '_ {
if !self.is_regexp_compiled() {
self.regexp_data.replace(Some(self.compile_regexp()));
}
Ref::map(self.regexp_data.borrow(), |it| &it.unwrap().regexp)
}
我该如何解决?
解决方案
Ref::map
您可以通过.as_ref()
将 转换&Option<_>
为 a来修复版本Option<&_>
,以便解包作为参考:
fn regexp(&self) -> impl Deref<Target = regex::Regex> + '_ {
if !self.is_regexp_compiled() {
self.regexp_data.replace(Some(self.compile_regexp()));
}
Ref::map(self.regexp_data.borrow(), |it| &it.as_ref().unwrap().regexp)
// ^^^^^^^^
}
在这种情况下,我建议OnceCell
从once_cell板条箱中使用:
use once_cell::sync::OnceCell;
pub struct RegexpData {
regexp: regex::Regex,
string: String,
}
pub struct RegExpFilter {
regexp_data: OnceCell<RegexpData>,
}
impl RegExpFilter {
pub fn compile_regexp(&self) -> RegexpData {
unimplemented!()
}
fn regexp(&self) -> ®ex::Regex {
&self.regexp_data.get_or_init(|| self.compile_regexp()).regexp
}
}
您可以简单地使用get_or_init
来获得相同的效果。OnceCell
和Lazy
(在同一个箱子中)对于惰性评估非常方便。
在操场上看到它。
推荐阅读
- c# - 在centos 7 mysql上运行的Web-Api dontnet core 2.2不工作
- html - 引导断点 - 有问题
- reactjs -
标签在 IE11 React 应用程序中无法识别 - javafx - JavaFX:也将鼠标事件传递给被遮挡的节点
- c - 计数连续的 1 位而不重叠
- java - JPA EntityGraph 在事务外抛出 LazyInitializationException
- curl - 无法获取 Github 组织存储库的问题
- sql - 如何将行转换为列 - 复杂的枢轴
- javascript - 如何命名一个新方法并让它通过一个函数?
- terraform - TFE cli 更新工作区时出错