我想用一个数组作为其字段之一来实现该结构的迭代器。迭代器应返回该数组的一个切片,但这需要一个生命周期参数。该参数应该去哪里?
Rust版本是1.37.0
struct A {
a: [u8; 100],
num: usize,
}
impl Iterator for A {
type Item = &[u8]; // this requires a lifetime parameter, but there is none declared
fn next(&mut self) -> Option<Self::Item> {
if self.num >= 10 {
return None;
}
let res = &self.a[10*self.num..10*(self.num+1)];
self.num += 1;
Some(res)
}
}
当您从函数返回引用时,其生存期需要与其他事物联系在一起。否则,编译器将不知道引用有效的时间(此例外是'static
生存期,该生存期将持续整个程序的持续时间)。
因此,我们需要现有的切片参考。一种标准的方法是将引用绑定到迭代器本身。例如,
struct Iter<'a> {
slice: &'a [u8; 100],
num: usize,
}
然后您所拥有的几乎是逐字记录的。 (我将类型和字段的名称更改为更具信息性)。
impl<'a> Iterator for Iter<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.num >= 100 {
return None;
}
let res = &self.slice[10 * self.num..10 * (self.num + 1)];
self.num += 1;
Some(res)
}
}
现在,您可能仍然在某个地方有实际的[u8; 100]
,而不仅仅是参考。如果仍要使用它,则需要一个单独的结构,该结构具有一种可以转换为A
的方法。例如
struct Data {
array: [u8; 100],
}
impl Data {
fn iter<'a>(&'a self) -> Iter<'a> {
Iter {
slice: &self.array,
num: 0,
}
}
}
由于使用了寿命删除,可以省略iter
上的寿命:
impl Data {
fn iter(&self) -> Iter {
Iter {
slice: &self.array,
num: 0,
}
}
}
只需几个注释。 [0u8; 100]
出现一个编译器错误。这可能是[u8; 100]
的错字,但以防万一,这就是为什么我们不能这样做。在结构定义的字段中,仅指定类型。没有默认值或类似的字段。如果您尝试使用默认结构,请考虑使用Default
trait。
其次,您可能已经意识到这一点,但是已经有Default
个切片的块迭代器。如果an implementation是切片(或可以将其解压缩为切片-向量和数组是主要示例),则slice
是该切片的长度为slice.chunks(n)
的块上的迭代器。我在上面链接的代码中给出了一个示例。有趣的是,该实现使用了一个非常相似的想法:slice.chunks(n)返回一个带有生命周期参数的新结构,并实现了n
。这几乎与我们的Iterator
完全相同。
最后,您的Data::iter
实现中存在一个错误,该错误在运行时会导致越界恐慌。看看是否可以发现它!