我查看了Drain Filter的Drop实现,以确保它删除所有剩余的元素,并且我注意到它在每drop(item);个元素周围都有一个DropGuard for Self(这是Drain Filter迭代器).这个卫兵有什么用处?除非drop(item);人感到panic ,否则我看不出这么做的目的.这仅仅是为了确保即使发生panic 也能移除其余物品吗?为什么不使用CATCH_UNWIND呢?

相关删除实施:

impl<T, F> Drop for DrainFilter<'_, T, F>
where
    F: FnMut(&mut T) -> bool,
{
    fn drop(&mut self) {
        struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>)
        where
            F: FnMut(&mut T) -> bool;

        impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F>
        where
            F: FnMut(&mut T) -> bool,
        {
            fn drop(&mut self) {
                self.0.for_each(drop);
            }
        }

        while let Some(item) = self.next() {
            let guard = DropGuard(self);
            drop(item);
            mem::forget(guard);
        }
    }
}

推荐答案

是的,这是为了防止item名 destruct 者panic 的情况.此模式在标准库中多次使用(在外来 crate 中也是如此).

catch_unwind()有两个缺点:

  1. 空降守卫比catch_unwind()更可优化.它们几乎总是在快乐的道路上得到正确的优化,而catch_unwind()则不是.此外,它们在panic 之路上的成本也更低,因为不需要达到resume_unwind().

  2. 双重panic .如果另一个元素的 destruct 者在我们处于panic 之中时panic ,会发生什么?有了空降卫兵,这是一次艰难的失败.这与语言的其余部分是一致的,在其他语言中,双重panic 会导致硬中止.然而,对于catch_unwind(),使用简单的方法(catch_unwind()+清理代码+resume_unwind()),这会导致第一个死机被忽略,这可能不是用户预期的,并且正确地处理这个问题需要两个catch_unwind().

Rust相关问答推荐

即使参数和结果具有相同类型,fn的TypId也会不同

基于对vec值的引用从该值中删除该值

新创建的变量的绑定生存期

取得本地对象字段的所有权

我应该将哪些文件放入我的GitHub存储库

在生存期内将非静态可变引用转换为范围内的静态可变引用

为什么 `Deref` 没有在 `Cell` 上实现?

Rust,如何从 Rc> 复制内部值并返回它?

随机函数不返回随机值

可选包装枚举的反序列化

仅在使用 &mut 或线程时borrow 的数据在闭包之外转义?

sha256 摘要仅适用于 &*

在 Bevy 项目中为 TextureAtlas 精灵实施 NearestNeighbor 的正确方法是什么?

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

是否有适当的方法在参考 1D 中转换 2D 数组

Rustfmt 是否有明确类型的选项?

制作嵌套迭代器的迭代器

BigUint 二进制补码

如何将 u8 切片复制到 u32 切片中?

为什么这里需要类型注解?