如何处理已检查迭代器

How to handle checked iterators?

本文关键字:检查 迭代器 处理 何处理      更新时间:2023-10-16

对于VS2013中的调试模式,如果我向迭代器添加常量值,则会收到超出范围的异常,并且该迭代器之后将超出范围。

例如:

#include <cstdlib>
#include <vector>
int main(void) {
    std::vector<unsigned char> data(10, 0);
    auto it = data.begin();
    while (it != data.end()) {
        if ((it + 3) <= data.end()) {
            it += 3;
        }
        else {
            it = data.end();
        }
    }
    return EXIT_SUCCESS;
}

while -循环的第四次运行中,检查it + 3 <= data.end()失败并抛出异常。

VS编译器的一个简单的解决方法是插入#define _ITERATOR_DEBUG_LEVEL 0,在调试模式下禁用检查迭代器的选项。

但我希望有一个更好的,通用的解决方案,将工作,VS和GCC编译器!我确信STL已经存在一种方法来处理迭代器的距离和检查,但我还不知道…

较好的通用解决方案如下

while ( std::distance( it, data.end() ) >= 3 )
{
    // some code
    std::advance( it, 3 );
    // some code
}

while ( it != data.end() )
{
    // some code
    std::advance( it, std::min<int>( 3, std::distance( it, data.end() ) ) );
    // some code
}

这两个变量之间的选择取决于您是否希望至少处理一次迭代器,即使data.end()小于3。

如果使用非随机访问迭代器,则循环看起来像

while ( it != data.end() )
{
    // some code
    ( ++it != data.end() ) && ( ++it != data.end() ) && ( ++it != data.end() );
    // some code
}

这是因为end()指向向量的最后一个实际元素之外的元素。因此,您的条件if ((it + 3) <= data.end())最终将计算为end() + 1(当it已经等于end()时),这是无效的。修改为if ((it + 3) < data.end())

重申一下:vector或任何其他STL容器的最后一个可用元素位于end() - 1。如果容器为空,则begin()end()相同。对指向end()的迭代器解引用总是错误的。