2

I am a novice C++ programmer working through a simple problem to print out name-and-score pairs together. Here I have used a std::unordered_set for the names and a vector for the scores (to accept duplicate scores, but not names) and that works fine.

But one thing puzzles me about the result, and that's that if I try to initialize the iterator in the for loop, the compiler gives me an error that says

the iterator "cannot be defined in the current scope."

This gives the error:

for (int i = 0, std::unordered_set<std::string>::iterator it = names.begin();
                                                i < names.size(); i++, it++)
{
    std::cout << *it << ", " << scores[i] << '\n';
}

But moved outside the loop, it works fine:

std::unordered_set<std::string>::iterator it = names.begin();
for (int i = 0; i < names.size(); i++, it++)
{
    std::cout << *it << ", " << scores[i] << '\n';
}

Why must the iterator be initialized outside the loop here? Sorry for the simple question, I've searched elsewhere and have not found a clear answer for this.

JeJo
  • 30,635
  • 6
  • 49
  • 88
Asta Lee
  • 35
  • 5
  • 8
    You can only declare variables with the same type in the first section of `for`, so either the iterator or the integer. – mch Aug 04 '21 at 07:33
  • Does this answer your question? [Is there a way to define variables of two different types in a for loop initializer?](https://stackoverflow.com/questions/866012/is-there-a-way-to-define-variables-of-two-different-types-in-a-for-loop-initiali) – Sreeraj Chundayil Aug 04 '21 at 07:42
  • 1
    Unrelated, but you should use a [pre-increment whenever dealing with iterators](https://stackoverflow.com/questions/1077026/incrementing-iterators-is-it-more-efficient-than-it), so `++it` (For integers, doing either `i++` or `++i` doesn't cause too much of a difference.) This is because, `std::unordered_set::iterator` is a class so doing `it++` potentially creates useless copies over on each iteration, which might not be relevant in most scenarios or the compiler might optimize it away if it is smart enough. But, as good practice, you should still prefer `++it` over `it++`. – Ruks Aug 04 '21 at 07:47
  • Ah, that was the piece I was missing. I didn't realize the variables had to be of the same type. That was an insightful thread, InQusitive- I hadn't thought about using pair or creating a separate scope with {} in particular. Also thanks for the advice about pre-incrementing, Ruks! – Asta Lee Aug 04 '21 at 07:50

1 Answers1

3

In C++ for-loop

for ( declaration-or-expression(optional) ; declaration-or-expression(optional) ; expression(optional) )
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

init-statement

  • either an expression statement (which may be a null statement ";")
  • a simple declaration, typically a declaration of a loop counter variable with initializer, but it may declare arbitrary many variables Note that any init-statement must end with a semicolon ;, which is why it is often described informally as an expression or a declaration followed by a semicolon.

Therefore, you can either declare the variable of the same type; ex:

for (int i = 0, j = 1; ... ; i++, j++) {...}
     ^^^^^^^^^^^^^^^^

or initialize the variables of any type that you have declared previously. Ex

std::unordered_set<std::string>::iterator it;
int i;
for (it = names.begin(),  i = 0; i < names.size(); i++, it++) { ... }
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^

Hence, your attempt is failed.

JeJo
  • 30,635
  • 6
  • 49
  • 88