对于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()
的迭代器解引用总是错误的。