Rust 迭代器返回的对象中的可变引用
我想创建一个Rust 迭代器返回的对象中的可变引用,rust,Rust,我想创建一个迭代器,该迭代器也能够公开相邻的项。只要我不想也改变这些项目,这是好的和容易的。但如何使同一结构的可变变体 不变的: struct NearestNeighbours2D<'a, T> { mid: &'a T, left: &'a T, right: &'a T, top: &'a T, bot: &'a T, } struct EnumerateNearestNeighbours2D&l
迭代器
,该迭代器也能够公开相邻的项。只要我不想也改变这些项目,这是好的和容易的。但如何使同一结构的可变变体
不变的:
struct NearestNeighbours2D<'a, T> {
mid: &'a T,
left: &'a T,
right: &'a T,
top: &'a T,
bot: &'a T,
}
struct EnumerateNearestNeighbours2D<'a, I>
where I: std::ops::Index<usize> {
x: usize,
y: usize,
width: usize,
height: usize,
inner: &'a I
}
impl<'a, I: std::ops::Index<usize>> Iterator for EnumerateNearestNeighbours2D<'a, I>
where <I as std::ops::Index<usize>>::Output: std::marker::Sized {
type Item = NearestNeighbours2D<'a, I::Output>;
fn next(&mut self) -> std::option::Option<<Self as std::iter::Iterator>::Item> {
let (top, left, mid, right, bot) = (
(self.y - 1) * self.width + self.x,
self.y * self.width + self.x - 1,
self.y * self.width + self.x,
self.y * self.width + self.x + 1,
(self.y + 1) * self.width + self.x,
);
Some(
NearestNeighbours2D {
mid: &self.inner[mid],
left: &self.inner[left],
right: &self.inner[right],
top: &self.inner[top],
bot: &self.inner[bot],
}
)
}
}
不幸的是,
EnumerateNearestNears2DMUT
无法正确生成,这是不合理的。每次调用next
都会得到&mut
引用,这些引用可能与上次调用next
返回的&mut
引用重叠。这意味着,如果它起作用,它将通过创建别名&mut
s来违反引用规则
这与有一个相同的原因,但没有WindowsMut
(尽管ChunksMut
是可以的,因为块是不重叠的)
有些问题()给出了类似的错误消息,但实际上是可以解决的(在某些情况下是不安全的),因为所引用的项实际上是不重叠的。这些解决方案在这里行不通。如果你可以(一个“流迭代器”),这个API就可以被完善。但是,Iterator
不允许这样做
这里有三种可能的选择。当然还有其他的
- 根本不允许可变迭代(使用邻居)。只需通过共享(
)引用公开迭代,如果需要修改原始网格,则创建一个修改后的副本,并在完成迭代后将其与原始网格交换。不管怎样,这通常是您想要的,如果您正在编写图像过滤器或细胞自动机之类的东西,其中每个输出都依赖于多个输入&
- 接受闭包并在API中使用内部迭代,而不是外部迭代。因此,不要像这样:
for neighbors in array.enumerate_2d_neighbors_mut() { println!("{}", neighbors.top); }
你可以这样写:array.foreach_2d_neighbors_mut(|neighbors| { println!("{}", neighbors.top); });
for neighbors in array.enumerate_2d_neighbors_mut() { println!("{}", neighbors.top); }
在这种情况下,对array.foreach_2d_neighbors_mut(|neighbors| { println!("{}", neighbors.top); });
项的引用在数组
方法内的foreach\u 2d\u neights\u mut
循环中进行,并且不转义它。即使没有for
代码,也可以非常轻松地编写此APIsafe
- 使用内部可变性(
,单元格
,参考单元格
等)通过原子???
和
引用进行变异,而不需要
。取决于你在做什么,这可能是正确的方法。要知道你可以。然而,在大多数情况下,这并不是我的第一选择&mut
Cell
,它指出的第一件事就是我犯的错误:“[…]只可能有以下之一:对对象有几个不可变的引用(&T)(也称为别名)。对对象有一个可变引用(&mut)(也称为易变性)。”。我只在读取时需要它来“混合”相邻元素并保存在不同的缓冲区中,但我想知道“如果”会怎样,以防将来需要它:D