gpt4 book ai didi

rust - Iterator::unzip 中 SizeHint 的用途是什么?

转载 作者:行者123 更新时间:2023-11-29 07:46:28 26 4
gpt4 key购买 nike

来自 Rust 标准库 implementation of unzip :

fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where
FromA: Default + Extend<A>,
FromB: Default + Extend<B>,
Self: Sized + Iterator<Item=(A, B)>,
{
struct SizeHint<A>(usize, Option<usize>, marker::PhantomData<A>);
impl<A> Iterator for SizeHint<A> {
type Item = A;

fn next(&mut self) -> Option<A> { None }
fn size_hint(&self) -> (usize, Option<usize>) {
(self.0, self.1)
}
}

let (lo, hi) = self.size_hint();
let mut ts: FromA = Default::default();
let mut us: FromB = Default::default();

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

for (t, u) in self {
ts.extend(Some(t));
us.extend(Some(u));
}

(ts, us)
}

这两行:

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

实际上不要对 tsus 进行任何扩展,因为 SizeHintnext 方法返回 。这样做的目的是什么?

最佳答案

这是一个很酷的把戏。通过提供此大小提示,它为 tsus 提供了为循环中的 extend 调用保留空间的机会。根据documentation

size_hint() is primarily intended to be used for optimizations such as reserving space for the elements of the iterator, but must not be trusted to e.g. omit bounds checks in unsafe code. An incorrect implementation of size_hint() should not lead to memory safety violations.

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

但是查看 Vec 的代码, 这将无效(在 HashMapVecDeque 中均无效)。其他 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);
}
}
}
}

关于rust - Iterator::unzip 中 SizeHint 的用途是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37074656/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com