Подтвердить что ты не робот

Как написать цикл for, который использует как итератор, так и счетчик индексов?

У меня есть функция, которая выглядит так:

void myclass::myfunc()
{
    int i;
    for( std::vector<Foo>::iterator it = var.begin(), i = 0; it < var.end(); it++, i++ )
    {
        /* ... */
    }
}

Я получаю эту ошибку:

Невозможно преобразовать из int в std::_Vector_iterator<>

Что не так с этим кодом?

4b9b3361

Ответ 1

Вы можете сделать это следующим образом:

int i = 0;
for( std::vector<int>::iterator it = v.begin(); it < v.end(); ++it, ++i){}

Ответ 2

Проблема заключается в этой части цикла for:

std::vector<Foo>::iterator it = var.begin(), i = 0

С++ интерпретирует это не как два оператора, разделенных запятыми, а как объявление переменной для переменной с именем it, которая является итератором, и как новое объявление переменной i, что итератор и инициализируется на 0. Ошибка состоит в том, что вы не можете инициализировать итератор vector равным 0.

Чтобы исправить это, вам нужно поднять определение вне цикла:

int i = 0;
std::vector<Foo>::iterator it = var.begin();
for(; it < var.end(); it++, i++ )
{
     // ...
}

Или переместите инициализацию i вне цикла:

int i = 0;
for( std::vector<Foo>::iterator it = var.begin(); it < var.end(); it++, i++ )
{
    // ...
}
Тем не менее, существует один последний вариант. Если вам нужно отслеживать индекс в векторе, который вы сейчас просматриваете, вы можете просто использовать подсчет для цикла (без итератора) или использовать только итератор и использовать вычитание итератора для восстановления индекса:
for (auto it = var.begin(); it != var.end(); ++it) {
    // current position is it - var.begin();
}

Надеюсь, это поможет!

Ответ 3

Избавьтесь от части i=0; (по крайней мере, внутри заголовка цикла).

Кроме того, если вы настаиваете на этом, подумайте о том, чтобы использовать:

for (auto it : var)

или

for (auto it = var.begin(); it != var.end(); ++it)

... вместо этого. Так как вы все равно используете итератор с произвольным доступом, то, что у вас есть как i, эквивалентно it - var.begin(). И наоборот, вы можете просто использовать:

for (int i=0; i<var.size(); i++)

... и при необходимости получить итератор в качестве var.begin() + i.

В зависимости от того, что в теле цикла, вы, вероятно, хотите полностью избавиться от цикла и заменить его алгоритмом.

Ответ 4

Двойная итерация:

using std::begin; using std::end;
for (auto p = std::make_pair( begin(var), 0 ); p.first != end(var); ++p.first, ++p.second ) {
  /* ... */
}

двойная итерация с именованными индексами/итераторами:

using std::begin; using std::end;
int i;
std::vector<Foo>::iterator it;
for (std::tie( it, i ) = std::make_pair( begin(var), 0 ); it != end(var); ++it, ++i ) {
  /* ... */
}

или привязать указанную пару на каждой итерации к более лучшим именованным переменным:

using std::begin; using std::end;
for (auto p = std::make_pair( begin(var), 0 ); p.first != end(var); ++p.first, ++p.second ) {
  auto const& it = p.first;
  int i = p.second;
}