来自Rust标准库implementation of unzip
:
ts.extend(SizeHint(lo, hi, marker::PhantomData));
us.extend(SizeHint(lo, hi, marker::PhantomData));
这两行:
ts
由于us
next
方法返回SizeHint
,因此实际上不要将None
或{{1}}扩展为任何内容。这样做的目的是什么?
答案 0 :(得分:5)
这是一个很酷的技巧。通过提供此大小提示,它为ts
和us
提供了为循环中的extend
调用保留空间的机会。根据{{3}}
size_hint()
主要用于优化,例如为迭代器的元素保留空间,但不得信任,例如,省略不安全代码中的边界检查。size_hint()
的错误实施不应导致内存安全违规。
请注意,创建SizeHint
是必要的,因为for extend
调用for循环是使用Some
值(Optional
实现Iterator
特征),size_hint
值的Some
为(1, Some(1))
。这对预分配没有帮助。
但是查看documentation
的代码,这将无效(在Vec
和HashMap
中都没有)。其他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>