Может кто-нибудь сказать мне, как увеличить итератор на 2?
iter++
- мне нужно сделать iter+2
? Как я могу достичь этого?
Может кто-нибудь сказать мне, как увеличить итератор на 2?
iter++
- мне нужно сделать iter+2
? Как я могу достичь этого?
Этот метод будет работать для итераторов, которые не являются итераторами с произвольным доступом, но по-прежнему могут быть специализированы при реализации не менее эффективно, чем iter += 2
при использовании с итераторами с произвольным доступом.
http://www.cplusplus.com/reference/std/iterator/advance/
std::advance(it,n);
где n - 2 в вашем случае.
Красота этой функции заключается в том, что если "it" является итератором произвольного доступа, быстрый
it += n
Используется операция (т.е. вектор <, > :: итератор). В противном случае его отображаемый
for(int i = 0; i < n; i++)
++it;
(т.е. список <.. > :: итератор)
Если у вас нет модифицируемого lvalue итератора или желательно получить копию заданного итератора (оставив исходный без изменений), тогда С++ 11 будет иметь новые вспомогательные функции - std::next
/std::prev
:
std::next(iter, 2); // returns a copy of iter incremented by 2
std::next(std::begin(v), 2); // returns a copy of begin(v) incremented by 2
std::prev(iter, 2); // returns a copy of iter decremented by 2
Вы можете использовать оператор "назначение по добавлению"
iter += 2;
Если вы не знаете, что у вас достаточно следующих элементов в вашем контейнере, или нет, вам нужно проверить его конец с каждым приращением. Ни ++, ни std:: advance не сделают это для вас.
if( ++iter == collection.end())
... // stop
if( ++iter == collection.end())
... // stop
Вы можете даже перевернуть свою собственную связанную безопасную функцию перехода.
Если вы уверены, что не пройдете мимо конца, то наилучшим решением будет std:: advance (iter, 2).
Мы можем использовать как std :: advance, так и std :: next, но между ними есть разница.
advance
изменяет свой аргумент и ничего не возвращает. Так что его можно использовать как:
vector<int> v;
v.push_back(1);
v.push_back(2);
auto itr = v.begin();
advance(itr, 1); //modifies the itr
cout << *itr<<endl //prints 2
next
возвращает измененную копию итератора:
vector<int> v;
v.push_back(1);
v.push_back(2);
cout << *next(v.begin(), 1) << endl; //prints 2
Предполагая, что размер списка не может быть даже кратным шагу, вы должны защититься от переполнения:
static constexpr auto step = 2;
// Guard against invalid initial iterator.
if (!list.empty())
{
for (auto it = list.begin(); /*nothing here*/; std::advance(it, step))
{
// do stuff...
// Guard against advance past end of iterator.
if (std::distance(it, list.end()) > step)
break;
}
}
В зависимости от реализации коллекции вычисление расстояния может быть очень медленным. Ниже приведено оптимальное и читаемое. Закрытие может быть изменено на шаблон утилиты со значением конца списка, переданным по ссылке const:
const auto advance = [&](list_type::iterator& it, size_t step)
{
for (size_t i = 0; it != list.end() && i < step; std::next(it), ++i);
};
static constexpr auto step = 2;
for (auto it = list.begin(); it != list.end(); advance(it, step))
{
// do stuff...
}
Если цикл отсутствует:
static constexpr auto step = 2;
auto it = list.begin();
if (step <= list.size())
{
std::advance(it, step);
}
Самый простой ответ:
++++iter
Длинный ответ:
Вы действительно должны привыкнуть писать ++iter
вместо iter++
. Последний должен вернуть (копию) старое значение, которое отличается от нового значения; это требует времени и пространства.
Обратите внимание, что приращение префикса (++iter
) принимает значение lvalue и возвращает значение lvalue, тогда как приращение постфикса (iter++
) принимает значение lvalue и возвращает значение r.