- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想创建一个控制修改的可变迭代器,为此,我创建了一个名为FitnessIterMut
的结构,该结构impl
Iterator
特性。next()
方法提供了一个结构,该结构可以在完成修改后对容器本身执行操作。 (这是做这种事情的好方法吗?)
pub struct FitnessModifier<'a, T: 'a> {
wheel: &'a mut RouletteWheel<T>,
value: &'a mut (f32, T)
}
impl<'a, T> FitnessModifier<'a, T> {
pub fn read(&'a self) -> &'a (f32, T) {
self.value
}
pub fn set_fitness(&'a self, new: f32) {
let &mut (ref mut fitness, _) = self.value;
self.wheel.proba_sum -= *fitness;
self.wheel.proba_sum += new;
*fitness = new;
}
}
pub struct FitnessIterMut<'a, T: 'a> {
wheel: &'a mut RouletteWheel<T>,
iterator: &'a mut IterMut<'a, (f32, T)>
}
impl<'a, T> Iterator for FitnessIterMut<'a, T> {
type Item = FitnessModifier<'a, T>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(value) = self.iterator.next() {
Some(FitnessModifier { wheel: self.wheel, value: value })
}
else {
None
}
}
}
'b
一生,但是我有点迷路了。
error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements [E0495]
Some(FitnessModifier { wheel: self.wheel, value: value })
^~~~~~~~~~
help: consider using an explicit lifetime parameter as shown: fn next(&'a mut self) -> Option<Self::Item>
fn next(&mut self) -> Option<Self::Item> {
if let Some(value) = self.iterator.next() {
Some(FitnessModifier { wheel: self.wheel, value: value })
}
else {
None
最佳答案
除非您可以不实现标准的Iterator
特征,否则您将无法使它与简单的可变引用一起使用。这是因为在Rust中,对一个特定值同时具有多个可用的可变别名是不合法的(因为这可能导致内存不安全)。让我们看看为什么您的代码违反了此限制。
首先,我可以实例化FitnessIterMut
对象。从该对象,我可以调用next
以获得FitnessModifier
。此时,FitnessIterMut
和FitnessModifier
都包含对RouletteWheel
对象的可变引用,并且FitnessIterMut
和FitnessModifier
仍然可用–这是不合法的!我可以再次在next
上调用FitnessIterMut
以获得另一个FitnessModifier
,现在我对RouletteWheel
具有3个可变别名。
您的代码无法编译,因为您假设可以复制可变引用,而事实并非如此。不变引用(&'a T
)实现Copy
,但可变引用(&'a mut T
)不实现,因此无法复制。
我们可以做些什么来解决这个问题? Rust使我们可以通过重新借用暂时使可变引用不可用(即,如果尝试使用它,则会出现编译器错误)。通常,对于未实现Copy
的类型,编译器将移动值而不是将其复制,但是对于可变引用,编译器将重新借款而不是移动。重新借用可以看作是对引用的“扁平化”或“崩溃”引用,同时保持最短的生命周期。
让我们看看这在实践中是如何工作的。这是next
的有效实现。请注意,这不符合标准Iterator
特性的约定,因此我将其设为固有方法。
impl<'a, T> FitnessIterMut<'a, T> {
fn next<'b>(&'b mut self) -> Option<FitnessModifier<'b, T>> {
if let Some(value) = self.iterator.next() {
Some(FitnessModifier { wheel: self.wheel, value: value })
}
else {
None
}
}
}
Option<FitnessModifier<'a, T>>
,而是返回
Option<FitnessModifier<'b, T>>
,其中
'b
与
self
参数的生存期链接。当初始化结果
wheel
的
FitnessModifier
字段时,编译器将自动从
self.wheel
中重新借用(我们可以通过编写
&mut *self.wheel
而不是
self.wheel
使其明确)。
&'a mut RouletteWheel<T>
,因此您认为此表达式的类型也将是
&'a mut RouletteWheel<T>
。但是,由于此表达式是从
self
借用的
&'b mut FitnessIterMut<'a, T>
,因此此表达式的类型实际上是
&'b mut RouletteWheel<T>
。在您的代码中,您尝试将
&'b mut RouletteWheel<T>
分配给需要
&'a mut RouletteWheel<T>
的字段,但是
'a
比
'b
长,这就是为什么会出现编译器错误的原因。
&'b mut RouletteWheel<T>
到
FitnessModifier
中,而必须存储
&'b &'a mut RouletteWheel<T>
,其中
'a
是
RouletteWheel<T>
的生存期,
'b
是
&'a mut RouletteWheel<T>
的生存期在
FitnessIterMut<'a, T>
中。但是,Rust使我们可以将该引用“折叠”为引用,并且我们可以只存储
&'b mut RouletteWheel<T>
(生存期为
'b
,而不是
'a
,因为
'b
的生存期较短)。
next
之后,您将无法使用
FitnessIterMut
,直到结果
Option<FitnessModifier<'b, T>>
超出范围。这是因为
FitnessModifier
是从
self
借用的,并且由于该方法是通过可变引用传递
self
的,因此编译器假定
FitnessModifier
保留了对
FitnessIterMut
或其字段之一的可变引用(在此是正确的,但并非总是如此一般的)。因此,尽管范围内有一个
FitnessModifier
,但
RouletteWheel
仅有一个可用的可变别名,它是
FitnessModifier
对象中的一个别名。当
FitnessModifier<'b, T>
超出范围时,
FitnessIterMut
对象将再次变得可用。
Iterator
特质,那么我建议您将可变引用替换为
Rc<RefCell<T>>
。
Rc
没有实现
Copy
,但是实现了
Clone
(仅克隆指针,而不克隆基础数据),因此您需要显式调用
.clone()
来克隆
Rc
。
RefCell
在运行时进行动态借阅检查,这有一点运行时开销,但在如何传递可变对象方面给了您更多自由。
关于iterator - 如何实现赋予结构生命周期的迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37366203/
我正在开发一个使用多个 turtle 的滚动游戏。玩家 turtle 根据按键命令在 Y 轴上移动。当危害和好处在 X 轴上移动时,然后循环并改变 Y 轴位置。我尝试定义一个名为 colliding(
我不明白为什么他们不接受这个作为解决方案,他们说这是一个错误的答案:- #include int main(void) { int val=0; printf("Input:- \n
我正在使用基于表单的身份验证。 我有一个注销链接,如下所示: 以及对应的注销方法: public String logout() { FacesContext.getCurren
在 IIS7 应用程序池中有一个设置 Idle-time out 默认是 20 分钟,其中说: Amount of time(in minutes) a worker process will rem
我是一名优秀的程序员,十分优秀!