首页 > 解决方案 > 手动迭代时如何避免下溢陷阱?

问题描述

下面的代码会因为j输入为usize.

fn foo(vec: &Vec<i32>) {
    let mut i = 0;
    let mut j = vec.len() - 1;
    while i < j {
        while i < j && !some_condition(vec[i]) {
            i += 1;
        }
        while i < j && !some_condition(vec[j]) {
            j -= 1;
        }
        if i < j {
            vec.swap(i, j);
            i += 1;
            j -= 1;
        }
    }
}

foo(&vec![]);

大多数情况下,迭代器有助于避免此类问题。但是当我们必须手动迭代索引时,我们真的需要小心。我可以检查vec前面的大小以避免恐慌。但这里真正的问题是我倾向于认为即使没有空检查,程序也会按预期工作,直到角落案例咬我。所以我想知道在 Rust 中是否有任何惯用的方式来做这种事情。

标签: rust

解决方案


您可以查看saturating_subchecked_sub

fn foo(vec: &Vec<i32>) {
    let mut i = 0;
    let mut j = vec.len().saturating_sub(1); 
    while i < j {
        // Some other logic
        i += 1;
        // EITHER
        j.saturating_sub(1); // avoid getting below 0
        //OR
        j = j.checked_sub(1).expect("usize underflow");
    }
}

foo(&vec![]);

如果您想要一些更复杂的处理而不是.expect()您可以使用:

j = j.checked_sub(1).ok_or_else(|| some_your_error_creator())?;

这似乎更惯用,但需要一些额外的错误处理工作。


推荐阅读