Что происходит, если Вы увеличиваете итератор, который равен в конец итератор контейнера STL

Производительность имеет значение .

62
задан Raedwald 29 November 2017 в 10:51
поделиться

7 ответов

Ниже приводится цитата из книги Николая Йосуттиса: пересекает ли он конец () последовательность (не может проверить, потому что итераторы вообще не знают контейнеры, на которых они работают). Таким образом, вызов этой функции может приводит к неопределенному поведению, потому что вызывающий оператор ++ для конца последовательность не определена

Другими словами, ответственность за поддержание итератора в пределах диапазона полностью лежит на вызывающей стороне.

62
ответ дан 24 November 2019 в 16:51
поделиться

Возможно, у вас должно быть что-то вроде этого:

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;
14
ответ дан 24 November 2019 в 16:51
поделиться

Предлагаю вам взглянуть на Boost.Range .
Может быть безопаснее использовать.
Он также будет в C ++ 0x.

2
ответ дан 24 November 2019 в 16:51
поделиться

Вы можете использовать функцию "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.
}
7
ответ дан 24 November 2019 в 16:51
поделиться

container.end () - элемент сразу за концом - это единственное определенное внешнее значение.

Проверенный итератор откажется от того, что, по сути, является доступом вне допустимого диапазона, но это не очень полезно (тем более, что поведение по умолчанию - завершение программы).

Я думаю, что лучшая практика - " не делайте этого "- либо проверяйте каждое значение итератора (желательно в чем-то обернутом как фильтр) и работайте только с интересными записями, либо явно используйте индекс с помощью

for(int i = 0; i < vec.size(); i+=2) {...}
1
ответ дан 24 November 2019 в 16:51
поделиться

Вы также можете сделать больше сравнений в своем операторе 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 элементами.

1
ответ дан 24 November 2019 в 16:51
поделиться
[

]Несмотря на то, что этому вопросу уже полгода, все равно было бы полезно упомянуть об использовании операторов сравнения > и <чтобы проверить, не проходила ли итерация после конца (или начала при обратной итерации) контейнера. Например:[

] [
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
]
-1
ответ дан 24 November 2019 в 16:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: