在 RefCell 中返回 Vec 的迭代器 [英] Returning iterator of a Vec in a RefCell

查看:17
本文介绍了在 RefCell 中返回 Vec 的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定以下 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() {}

我收到一条关于终身问题的错误消息:

I get an error message about a lifetime issue:

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

我怎样才能返回和使用 bars 迭代器?

How am I able to return and use bars iterator?

推荐答案

你不能这样做,因为它会让你绕过运行时检查唯一性违规.

You cannot do this because it would allow you to circumvent runtime checks for uniqueness violations.

RefCell 为您提供了一种将可变性排他性检查推迟"到运行时的方法,作为交换,它允许通过共享引用对其内部保存的数据进行突变.这是使用 RAII 守卫完成的:您可以使用对 RefCell 的共享引用获取守卫对象,然后使用此守卫对象访问 RefCell 内的数据:

RefCell provides you a way to "defer" mutability exclusiveness checks to runtime, in exchange allowing mutation of the data it holds inside through shared references. This is done using RAII guards: you can obtain a guard object using a shared reference to RefCell, and then access the data inside RefCell using this guard object:

&'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 引用的情况下&mutRefCell 的引用.但是,这些引用将链接到守卫,并且不能比守卫活得更长.这是有意完成的:RefRefMut 析构函数在其 RefCell 内切换各种标志以强制进行可变性检查并强制 borrow()<如果这些检查失败,/code> 和 borrow_mut() 会发生恐慌.

The key point here is that 'b is different from 'a, which allows one to obtain &mut T references without having a &mut reference to the RefCell. However, these references will be linked to the guard instead and can't live longer than the guard. This is done intentionally: Ref and RefMut destructors toggle various flags inside their RefCell to force mutability checks and to force borrow() and borrow_mut() panic if these checks fail.

您可以做的最简单的事情是返回一个围绕 Ref 的包装器,该引用将实现 IntoIterator:

The simplest thing you can do is to return a wrapper around Ref, a reference to which would implement 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()
    }
}

(尝试在操场上)

您不能直接为 VecRefWrapper 实现 IntoIterator,因为这样内部的 Ref 将被 into_iter(),给你基本上和你现在一样的情况.

You can't implement IntoIterator for VecRefWrapper directly because then the internal Ref will be consumed by into_iter(), giving you essentially the same situation you're in now.

这篇关于在 RefCell 中返回 Vec 的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆