返回RefCell中Vec的迭代器 [英] Returning iterator of a Vec in a RefCell
问题描述
鉴于以下 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() {}
我收到有关终身问题的错误消息:
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
我如何返回并使用 bar
s iterator?
How am I able to return and use bar
s iterator?
推荐答案
你不能这样做,因为它可以让你绕过运行时检查对于唯一性违规行为。
You cannot do this because it would allow you to circumvent runtime checks for uniqueness violations.
RefCell
为您提供了一种将可变性排他性检查推迟到运行时的方法,以换取允许它通过共享引用保存在内部的数据的变异。这是使用RAII警卫完成的:您可以使用对 RefCell
的共享引用获取一个保护对象,然后访问 RefCell $ c中的数据$ c>使用这个保护对象:
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
引用,而无需& mut
对 RefCell
的引用。但是,这些参考文献将与警卫相关联,并且不能比守卫更长寿。这是故意完成的: Ref
和 RefMut
析构函数切换其 RefCell $中的各种标志c $ c>强制进行可变性检查并强制
borrow()
和 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屋!