如果我将迭代器指向向量的最后一个元素时,它会增加2怎么办?在this question询问如何通过2个元素调整STL容器的迭代器提供了两种不同的方法:
-
使用算术运算符的形式 - = 2或两次
-
或使用std :: advance()
当迭代器指向STL容器的最后一个元素或更远时,我用VC 7测试了它们的边缘情况:
vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );
vector<int>::iterator it = vec.begin();
advance( it, 2 );
bool isAtEnd = it == vec.end(); // true
it++; // or advance( it, 1 ); - doesn't matter
isAtEnd = it == vec.end(); //false
it = vec.begin();
advance( it, 3 );
isAtEnd = it == vec.end(); // false
我已经看过有时可以建议在遍历vector和其他容器时与vector :: end()进行比较:
for( vector<int>::iterator it = vec.begin(); it != vec.end(); it++ ) {
//manipulate the element through the iterator here
}
显然,如果迭代器超出循环内的最后一个元素,则for循环语句中的比较将评估为false,并且循环将很快继续进入未定义的行为 .
我是否正确,如果我在迭代器上使用advance()或任何类型的递增操作并使它指向容器的末尾,我将无法检测到这种情况?如果是这样,最佳做法是什么 - 不使用这些进步?
8 回答
Marijn建议的代码只是略有错误(正如curiousguy指出的那样) .
最后一行的正确版本是:
我建议你看看Boost.Range .
使用起来可能更安全 .
它也将在C 0x中 .
以下是Nicolai Josuttis的书:
换句话说,将迭代器维持在该范围内的责任完全在于调用者 .
也许你应该有这样的东西:
当
iterator_category<Itr>
为random_access_iterator
时,您可以重载此操作以执行以下操作:您可以在迭代器(it)和vec.begin()上的迭代器之间使用“distance”函数,并将其与向量的大小(通过size()获得)进行比较 .
在这种情况下,你的for循环看起来像这样:
container.end() - 刚刚结束的元素 - 是唯一定义的外部值 .
检查的迭代器将在本质上是超出范围的访问时出错,但这并不是非常有用(特别是因为默认行为是结束程序) .
我认为最好的做法是“不要那样做” - 要么检查迭代器的每个值(最好是包含在过滤器中的东西),并且只对有趣的条目进行操作,要么明确地使用索引
for(int i = 0; i <vec.size(); i = 2)
您还可以在for语句中进行更多比较:
我不知道这对于Kostas's建议会如何表现,但感觉这对于一个小的增量会更好 . 当然,由于需要对每个增量进行检查,因此对于大增量来说是非常难以维护的,但这是另一种选择 .
如果可能的话,我肯定会避免它 . 如果你真的需要一次增加2个值,那么考虑使用std :: pair的向量或带有2个元素的struct的向量 .
尽管这个问题是半年之久,但提及比较运算符的使用>和<仍然有用,以检查是否迭代了容器的结束(或迭代开始时) . 例如: