存储可变引用和生命周期
Storing mutable references and lifetimes
我现在已经花了很多时间试图让它工作但毫无结果,但恐怕我现在唯一的办法就是尝试总结我的代码并向大家寻求帮助。
情况是,如果我在下面的代码中取消对 mut
的两个实例的注释,它将不再编译(并且不是出于对我有意义的原因):
use std::cell::RefCell;
use std::ops::Index;
struct Foo<'a, T: 'a> {
t_array: [T; 3],
t_refs: RefCell<Vec<&'a /* mut */ T>>, //' // 1
}
impl<'a, T> Foo<'a, T> {
fn new(t1: T, t2: T, t3: T) -> Foo<'a, T> { //'
Foo {
t_array: [t1, t2, t3],
t_refs: RefCell::new(Vec::with_capacity(3))
}
}
fn add_t_ref(&'a mut self, at_index: usize) { //'
let t_ref = & /* mut */ self.t_array[at_index]; // 2
let mut t_refs = self.t_refs.borrow_mut();
t_refs.push(t_ref);
}
}
impl<'a, T> Index<usize> for Foo<'a, T> {
type Output = T;
#[inline]
fn index(&self, index: &usize) -> &T {
let t_refs = self.t_refs.borrow();
t_refs[*index]
}
}
在 Vec
中存储 mut
引用时发生的错误是:
blah3_mut.rs:26:9: 26:15 error: `t_refs` does not live long enough
blah3_mut.rs:26 t_refs[*index]
^~~~~~
blah3_mut.rs:24:42: 27:6 note: reference must be valid for the anonymous lifetime #1 defined on the block at 24:41...
blah3_mut.rs:25:42: 27:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 25:41
如果有人能解释为什么会这样,我会很高兴;直觉上,RefCell
的借用超出范围似乎不应该成为问题。 Vec
(因此 RefCell
也不拥有引用指向的数据,那么为什么编译器关心 它们的 引用的生命周期?
P.S。我知道我的简化代码摘录并没有说明为什么我将可变引用存储在 Vec
中或者为什么我使用 RefCell
——足以说明这并非偶然 [=36] =]
P.P.S。我尝试在 index
方法 and/or 特征的关联类型上使用生命周期注解来搞乱一些,但到目前为止只设法从中得到不同的错误
它使用不可变引用的原因是它们可以被隐式复制。当您切换到尝试 return a &mut
时,将有两个地方具有该引用 - Vec 和函数的调用者。这将引入 别名,并且 Rust 中不允许使用可变别名。
您甚至可以忽略 Index
实现并尝试这样做:
fn main() {
let mut f = Foo::new(1,2,3);
f.add_t_ref(1);
f.add_t_ref(2);
}
您将获得:
error: cannot borrow `f` as mutable more than once at a time
虽然以上所有内容都是正确的,但它并不能真正解释为什么您会收到特定的错误消息。
我现在已经花了很多时间试图让它工作但毫无结果,但恐怕我现在唯一的办法就是尝试总结我的代码并向大家寻求帮助。
情况是,如果我在下面的代码中取消对 mut
的两个实例的注释,它将不再编译(并且不是出于对我有意义的原因):
use std::cell::RefCell;
use std::ops::Index;
struct Foo<'a, T: 'a> {
t_array: [T; 3],
t_refs: RefCell<Vec<&'a /* mut */ T>>, //' // 1
}
impl<'a, T> Foo<'a, T> {
fn new(t1: T, t2: T, t3: T) -> Foo<'a, T> { //'
Foo {
t_array: [t1, t2, t3],
t_refs: RefCell::new(Vec::with_capacity(3))
}
}
fn add_t_ref(&'a mut self, at_index: usize) { //'
let t_ref = & /* mut */ self.t_array[at_index]; // 2
let mut t_refs = self.t_refs.borrow_mut();
t_refs.push(t_ref);
}
}
impl<'a, T> Index<usize> for Foo<'a, T> {
type Output = T;
#[inline]
fn index(&self, index: &usize) -> &T {
let t_refs = self.t_refs.borrow();
t_refs[*index]
}
}
在 Vec
中存储 mut
引用时发生的错误是:
blah3_mut.rs:26:9: 26:15 error: `t_refs` does not live long enough
blah3_mut.rs:26 t_refs[*index]
^~~~~~
blah3_mut.rs:24:42: 27:6 note: reference must be valid for the anonymous lifetime #1 defined on the block at 24:41...
blah3_mut.rs:25:42: 27:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 25:41
如果有人能解释为什么会这样,我会很高兴;直觉上,RefCell
的借用超出范围似乎不应该成为问题。 Vec
(因此 RefCell
也不拥有引用指向的数据,那么为什么编译器关心 它们的 引用的生命周期?
P.S。我知道我的简化代码摘录并没有说明为什么我将可变引用存储在 Vec
中或者为什么我使用 RefCell
——足以说明这并非偶然 [=36] =]
P.P.S。我尝试在 index
方法 and/or 特征的关联类型上使用生命周期注解来搞乱一些,但到目前为止只设法从中得到不同的错误
它使用不可变引用的原因是它们可以被隐式复制。当您切换到尝试 return a &mut
时,将有两个地方具有该引用 - Vec 和函数的调用者。这将引入 别名,并且 Rust 中不允许使用可变别名。
您甚至可以忽略 Index
实现并尝试这样做:
fn main() {
let mut f = Foo::new(1,2,3);
f.add_t_ref(1);
f.add_t_ref(2);
}
您将获得:
error: cannot borrow `f` as mutable more than once at a time
虽然以上所有内容都是正确的,但它并不能真正解释为什么您会收到特定的错误消息。