给定以下 struct
和 impl
:
use std::slice::Iter;
use std::cell::RefCell;
struct Foo {
bar: RefCell<Vec<u32>>,
}
impl Foo {
pub fn iter(&self) -> Iter<u32> {
self.bar.borrow().iter()
}
}
fn main() {}
我收到有关生命周期问题的错误消息:
error: borrowed value does not live long enough
--> src/main.rs:9:9
|
9 | self.bar.borrow().iter()
| ^^^^^^^^^^^^^^^^^ does not live long enough
10 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the body at 8:36...
--> src/main.rs:8:37
|
8 | pub fn iter(&self) -> Iter<u32> {
| _____________________________________^ starting here...
9 | | self.bar.borrow().iter()
10 | | }
| |_____^ ...ending here
我怎样才能返回并使用 bar
的迭代器?
最佳答案
您不能这样做,因为它会允许您规避运行时检查是否违反唯一性。
RefCell
为您提供了一种将可变性排他性检查“推迟”到运行时的方法,作为交换,它允许通过共享引用对其内部保存的数据进行突变。这是使用 RAII 守卫完成的:您可以使用对 RefCell
的共享引用来获取守卫对象。 ,然后访问RefCell
里面的数据使用这个守卫对象:
&'a RefCell<T> -> Ref<'a, T> (with borrow) or RefMut<'a, T> (with borrow_mut)
&'b Ref<'a, T> -> &'b T
&'b mut RefMut<'a, T> -> &'b mut T
这里的关键点是'b
不同于'a
, 这允许一个人获得 &mut T
没有 &mut
的引用引用RefCell
.但是,这些引用将链接到守卫,并且不能比守卫长寿。这是故意的:Ref
和 RefMut
析构函数在其 RefCell
中切换各种标志强制进行可变性检查并强制 borrow()
和 borrow_mut()
如果这些检查失败, panic 。
您可以做的最简单的事情就是返回一个围绕 Ref
的包装器, 对其的引用将实现 IntoIterator
:
use std::cell::Ref;
struct VecRefWrapper<'a, T: 'a> {
r: Ref<'a, Vec<T>>
}
impl<'a, 'b: 'a, T: 'a> IntoIterator for &'b VecRefWrapper<'a, T> {
type IntoIter = Iter<'a, T>;
type Item = &'a T;
fn into_iter(self) -> Iter<'a, T> {
self.r.iter()
}
}
(试一试 on playground )
你不能实现IntoIterator
对于 VecRefWrapper
直接因为那么内部Ref
将被 into_iter()
消耗,给你的情况与你现在所处的情况基本相同。
关于iterator - 返回 RefCell 中 Vec 的迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43378300/