如果您递增一个等于 STL 容器的结束迭代器的迭代器,会发生什么
如果当迭代器指向向量的最后一个元素时将其增加 2 会怎样? 在这个问题询问如何将迭代器调整为STL容器2 个元素提供了两种不同的方法:
- 要么使用算术运算符的形式 - +=2 或 ++ 两次
- ,要么使用 std::advance()
我已经用 VC++ 7 测试了这两种方法的迭代器指向的边缘情况STL 容器或其他容器的最后一个元素:
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
我多次看到建议在遍历向量和其他容器时与向量 :: end() 进行比较:
for( vector<int>::iterator it = vec.begin(); it != vec.end(); it++ ) {
//manipulate the element through the iterator here
}
显然,如果迭代器前进到循环内的最后一个元素之后,则比较for-loop 语句中的值将评估为 false,并且循环将愉快地继续执行未定义的行为。
如果我在迭代器上使用 advance() 或任何类型的增量操作并使其指向容器的末尾,我将无法检测到这种情况,我是否理解正确? 如果是这样,最佳实践是什么 - 不使用此类进步?
What if I increment an iterator by 2 when it points onto the last element of a vector? In this question asking how to adjust the iterator to an STL container by 2 elements two different approaches are offered:
- either use a form of arithmetic operator - +=2 or ++ twice
- or use std::advance()
I've tested both of them with VC++ 7 for the edge case when the iterator points onto the last element of the STL container or beyond:
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
I've seen may times an advise to compare against vector::end() when traversing the vector and other containers:
for( vector<int>::iterator it = vec.begin(); it != vec.end(); it++ ) {
//manipulate the element through the iterator here
}
Obviously if the iterator is advanced past the last element inside the loop the comparison in the for-loop statement will evaluate to false and the loop will happily continue into undefined behaviour.
Do I get it right that if I ever use advance() or any kind of increment operation on an iterator and make it point past the container's end I will be unable to detect this situation? If so, what is the best practice - not to use such advancements?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
以下是 Nicolai Josuttis 书中的引述:
换句话说,将迭代器维护在范围内的责任完全由调用者承担。
Following is the quote from Nicolai Josuttis book:
In other words, the responsibility of maintaining the iterator within the range lies totally with the caller.
也许你应该有这样的东西:
当
iterator_category
是random_access_iterator
时,你可以重载它来执行如下操作:Perhaps you should have something like this:
You can overload this for when
iterator_category<Itr>
israndom_access_iterator
to do something like the following:您可以在迭代器 (it) 和 vec.begin() 处的迭代器之间使用“距离”函数,并将其与向量的大小(通过 size() 获得)进行比较。
在这种情况下,你的 for 循环将如下所示:
You could use the "distance" function between your iterator (it) and the iterator at vec.begin() and compare it with the vector's size (obtained by size()).
In that case your for loop would look like this:
Marijn 建议的代码只是略有错误(正如好奇的人指出的那样)。
最后一行的正确版本是:
The code that Marijn suggests is just slightly wrong (as curiousguy pointed out).
The correct version of the last line is:
您还可以在 for 语句中进行更多比较:
我不知道这与 Kostas的建议,但感觉就像小增量更好。 当然,对于较大的增量来说,这是相当难以维护的,因为您需要对每个增量进行检查,但这是另一种选择。
如果可能的话,我肯定会避免它。 如果您确实需要一次增加 2 个值,请考虑使用 std::pair 向量或具有 2 个元素的结构体向量。
You could also do more comparisons in your for statement:
I don't know how this would perform vs Kostas's suggestion, but it feels like it would be better for a small increment. Of course it would be pretty unmaintainable for a large increment since you need a check for each, but it is another option.
I would definitely avoid it if at all possible. If you really need to increment by 2 values at a time, then consider having a vector of std::pair or a vector of a struct with 2 elements.
我建议你看看 Boost.Range.
使用起来可能更安全。
它也将采用 C++0x。
I suggest you to take a look at Boost.Range.
It might be safer to use.
It will also be in C++0x.
container.end()
——刚刚超出末尾的元素——是唯一定义的外部值。受检查的迭代器将在本质上超出范围的访问上出错,但这并不是很有帮助(特别是因为默认行为是结束程序)。
我认为最好的做法是“不要这样做”——要么检查迭代器的每个值(最好是在包装为过滤器的东西中),并且只对感兴趣的条目进行操作,要么显式使用索引
container.end()
-- the element just past the end -- is the only defined exterior value.A checked iterator will fault on what is essentially an out-of-range access, but that isn't terribly helpful (especially as the default behaviour is to end the program).
I think the best practice is "don't do that" -- either check every value of the iterator (preferably in something wrapped as a filter), and only operate on interesting entries, or use the index explicitly with
尽管这个问题已经有半年历史了,但提及比较运算符 > 的使用可能仍然有用。 且< 检查您是否迭代超过了容器的末尾(或迭代回来时的开头)。 例如:
Even though this question is half a year old, it might still be useful to mention the use of comparison operators > and < to check if you iterated past the end (or the start when iterating back) of the container. For example: