iterator - 返回 RefCell 中 Vec 的迭代器

标签 iterator rust lifetime

给定以下 structimpl:

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 .但是,这些引用将链接到守卫,并且不能比守卫长寿。这是故意的:RefRefMut析构函数在其 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/

相关文章:

java - 我可以继承 "standard"arraylist 迭代器吗?

rust - 如何在过程宏中指定条件代码

c++ - 异步函数调用的参数生命周期

rust - 遍历中RefCell的循环引用借用

c# - 使用 CCR 有序处理事件的有效方法是什么?

c++ - Boost : Function Output Iterator, 重新发明轮子

c++ - 自定义迭代器和自定义常量迭代器之间的转换

rust - 为什么我会收到错误 "the trait ` Foo` is not implemented for `&mut T` “即使 T 实现了特征?

arrays - 在 Rust 中,我可以在不对值进行硬编码的情况下实例化我的 const 数组吗?编译时评估?

rust - 函数返回 serde 反序列化类型时如何修复生命周期错误?