Ниже приводится цитата из книги Николая Йосуттиса: пересекает ли он конец () последовательность (не может проверить, потому что итераторы вообще не знают контейнеры, на которых они работают). Таким образом, вызов этой функции может приводит к неопределенному поведению, потому что вызывающий оператор ++ для конца последовательность не определена
Другими словами, ответственность за поддержание итератора в пределах диапазона полностью лежит на вызывающей стороне.
Возможно, у вас должно быть что-то вроде этого:
template <typename Itr>
Itr safe_advance(Itr i, Itr end, size_t delta)
{
while(i != end && delta--)
i++;
return i;
}
Вы можете перегрузить это, когда iterator_category
is random_access_iterator
, чтобы сделать что-то вроде следующего:
return (delta > end - i)? end : i + delta;
Предлагаю вам взглянуть на Boost.Range .
Может быть безопаснее использовать.
Он также будет в C ++ 0x.
Вы можете использовать функцию "distance" между вашим итератором (it) и итератором в vec.begin () и сравнить ее с размером вектора (полученным с помощью size ()).
В этом случае цикл for будет выглядеть так:
for (vector<int>::iterator it = vec.begin(); distance(vec.begin(), it) < vec.size(); ++it)
{
// Possibly advance n times here.
}
container.end ()
- элемент сразу за концом - это единственное определенное внешнее значение.
Проверенный итератор откажется от того, что, по сути, является доступом вне допустимого диапазона, но это не очень полезно (тем более, что поведение по умолчанию - завершение программы).
Я думаю, что лучшая практика - " не делайте этого "- либо проверяйте каждое значение итератора (желательно в чем-то обернутом как фильтр) и работайте только с интересными записями, либо явно используйте индекс с помощью
for(int i = 0; i < vec.size(); i+=2) {...}
Вы также можете сделать больше сравнений в своем операторе for:
for( vector<int>::iterator it = vec.begin(); it != vec.end() && it+1 != vec.end(); it+=2 ) {
//manipulate the element through the iterator here
}
Я не знаю, как это будет работать по сравнению с предложением Костаса , но кажется , что было бы лучше за небольшую прибавку. Конечно, это было бы довольно трудно поддерживать для большого приращения, поскольку вам нужна проверка для каждого, но это еще один вариант.
Я бы определенно избегал этого, если это вообще возможно. Если вам действительно нужно увеличивать на 2 значения за раз, подумайте о наличии вектора std :: pair или вектора структуры с 2 элементами.
]Несмотря на то, что этому вопросу уже полгода, все равно было бы полезно упомянуть об использовании операторов сравнения > и <чтобы проверить, не проходила ли итерация после конца (или начала при обратной итерации) контейнера. Например:[
] [vector<int> vec;
vec.push_back( 1 );
vec.push_back( 2 );
vector<int>::iterator it = vec.begin();
it+=10; //equivalent to advance( it, 10 )
bool isPastEnd = it > vec.end(); //true
]