Iterator :: unzip中SizeHint的目的是什么?

时间:2016-05-06 14:13:33

标签: rust

来自Rust标准库implementation of unzip

ts.extend(SizeHint(lo, hi, marker::PhantomData));
us.extend(SizeHint(lo, hi, marker::PhantomData));

这两行:

ts
由于us next方法返回SizeHint,因此实际上不要将None或{{1}}扩展为任何内容。这样做的目的是什么?

2 个答案:

答案 0 :(得分:5)

这是一个很酷的技巧。通过提供此大小提示,它为tsus提供了为循环中的extend调用保留空间的机会。根据{{​​3}}

  

size_hint()主要用于优化,例如为迭代器的元素保留空间,但不得信任,例如,省略不安全代码中的边界检查。 size_hint()的错误实施不应导致内存安全违规。

请注意,创建SizeHint是必要的,因为for extend调用for循环是使用Some值(Optional实现Iterator特征),size_hint值的Some(1, Some(1))。这对预分配没有帮助。

但是查看documentation的代码,这将无效(在VecHashMap中都没有)。其他Extend实现可能不同。

执行ts.extend(SizeHint(lo, hi, marker::PhantomData));不会触发resize,因为next会返回None。也许有人应该写一个补丁。

impl<T> Vec<T> {
    fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
        // This function should be the moral equivalent of:
        //
        //      for item in iterator {
        //          self.push(item);
        //      }
        while let Some(element) = iterator.next() {
            let len = self.len();
            if len == self.capacity() {
                let (lower, _) = iterator.size_hint();
                self.reserve(lower.saturating_add(1));
            }
            unsafe {
                ptr::write(self.get_unchecked_mut(len), element);
                // NB can't overflow since we would have had to alloc the address space
                self.set_len(len + 1);
            }
        }
    }
}

答案 1 :(得分:4)

这是一个可疑的黑客!

它实现了一个带有假(过高估计)大小提示的迭代器,以鼓励生成的集合预先保留最终适当的容量。

酷技巧但是,它是通过实现一个大小提示来实现的,其中估计的下限大于实际生成的元素数(0)。如果未知下限,则迭代器应该返回0的下限。由于这个原因,这个实现可能是非常错误的,并且集合的Extend impl可能会导致bugginess(但当然不是内存不安全。)< / p>