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