如何处理已检查的迭代器?

时间:2014-05-07 10:32:19

标签: c++ iterator

对于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已经有办法处理迭代器距离和这样的检查:)但我还不知道......

2 个答案:

答案 0 :(得分:2)

更好的常见解决方案如下

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
}

答案 1 :(得分:1)

因为end()指向元素超出向量的最后一个实际元素。因此,您的条件if ((it + 3) <= data.end())最终会评估为end() + 1(当it已经等于end()时),这是无效的。要解决此问题,请将其更改为if ((it + 3) < data.end())

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