如何表示容器的Rust迭代器的生命周期

时间:2016-04-18 20:54:38

标签: rust

我有一个像这样的循环缓冲区:

struct CircularBuffer<T: Copy> {
    seqno: usize,
    data: Vec<T>,
}

我想创建一个外部结构作为迭代器。这个结构将引用CircularBuffer的内部数据向量,如下所示:

struct CircularBufferIterator<'a, T: 'a + Copy> {
    buffer: &'a CircularBuffer<T>,
    position: usize,
    limit: usize,
}

这是我能想到的最好的实际编译。您能否建议一种更好的方式来表达CircularBufferIterator取决于CircularBuffer对象?

让我感到困扰的是T: 'a + Copy。我想知道是否有可能或者说T类型不是CircularBuffer<T>,而CircularBufferIterator取决于'a

我看不到的部分是为什么我需要将T生命周期添加到T: Copy。没有一生,不能是T吗?换句话说,当CircularBuffer引用超过CircularBuffer时,我看不到这种情况。 CircularBufferIterator的参考资料比CircularBuffer更长。

function ToBinaryTree ( arr ) { // creates a binary tree from an array arr of comparable objects this.Tree = { left: undefined, right: undefined }; this.CreateNode = function ( value ) { return { val : undefined, left : undefined, right : undefined } }; this.Insert = function (elem) { var node = this.CreateNode(elem); if ( this.Tree.left == undefined ) // ... ?? }; // insert elements from array provided in "constructor" arr.forEach(function(x){ this.Insert(x); }.bind(this)); this.Contains = function (elem) { // ... }; return this; } 和上下文来自this blog post

1 个答案:

答案 0 :(得分:3)

  

为什么我需要将'a生命周期添加到T

您不能为T添加生命周期;你说的是,无论选择T,它只能包含超过'a的引用。如果情况并非如此,那么我们可能会引用一个现在无效的引用类型。使用该无效参考将导致记忆不安全; Rust希望避免的一件重要事情。

我原本以为你问的是如何删除Copy界限,所以这就是我输入的所有内容。

一个更改是从Copy中移除CircularBuffer绑定,但将其留在方法的实现上。然后你根本不需要在迭代器上使用它:

struct CircularBuffer<T> {
    seqno: usize,
    data: Vec<T>,
}

struct CircularBufferIterator<'a, T: 'a> {
    buffer: &'a CircularBuffer<T>,
    position: usize,
    limit: usize,
}

另一个变化是完全避免直接引用CircularBuffer,并将直接迭代器保留在Vec中:

struct CircularBufferIterator<'a, T: 'a> {
    first: std::slice::Iter<'a, T>,
    second: Option<std::slice::Iter<'a, T>>,
}

但是,查看Iterator实现,我看到它返回T而不是&T,因此您最终需要一个Copy或{{ 1}}。您会注意到标准库并不需要这样做,因为它返回对集合中项目的引用。如果您确实需要非参考,那就是CloneIterator::cloned的用途。