I have a simple Range-based loop:

int arr[3] = { 9, 7, 1 }; for (auto i: arr) std::cout << i << "\n"; 

The program will display the contents of the array:

 9 7 1 

And if I want to display more detailed information:

 массив[0] = 9 массив[1] = 7 массив[2] = 1 

How can I do without introducing an additional counter variable? or is it impossible?

  • Normal for (;;) to help. - Vladimir Gamalyan

3 answers 3

You can get the index of an element within range-for, but for this you need to change the type of the variable:

 #include <iostream> int main() { int arr[3] = { 9, 7, 1 }; for (auto& v: arr) std::cout << (&v - &arr[0]) << "-" << v << "\n"; } 

Conclusion:

 0-9 1-7 2-1 

Here we added & to auto so that the type of the variable being iterated is int& . So the loop variable is not a new copy, but a link to an array element. And since the array elements are arranged in memory sequentially, the expression (&v - &arr[0]) in this case will give the element offset from the beginning of the array, i.e. Essentially the index you need.

You may notice that the additional variable was not introduced for this, as other participants argued.

  • 2
    and if arr is std::vector<int> ? - KoVadim
  • one
    and if there inadvertently becomes std::list<int> ? - KoVadim
  • 3
    @KoVadim, then std::distance is our everything. With love, sincerely your house painter Slamiel. - ߊߚߤߘ
  • 2
    @Arhad: std::distance requires input iterators , not pointers to container elements. For std::vector (as in your example) this will work, for obvious reasons. Of course, this will not work for any other container until you find a way to convert pointers to elements into iterators. Direct conversion in the general case does not exist, for which reason std::distance cannot help here. - AnT
  • 2
    @Isaev: "The most correct answer" is not to use range-based for in situations when you need an index or an iterator of the current element. What is offered in this answer is acceptable for debugging purposes, but no more. - AnT

Obviously, in this sentence

 for (auto i: arr) std::cout << "i" << "\n"; ^^^^ 

you made a typo. Most likely you had in mind

 for (auto i: arr) std::cout << i << "\n"; ^^^^ 

As for your question, in addition to obtaining the values ​​of the elements of the array to obtain the values ​​of the indexes of the elements of the array, you will in any case have to enter an additional variable.

Therefore, in such cases it is better to use the usual for clause.

 for ( size_t i = 0; i < sizeof( arr ) / sizeof( *arr ); i++ ) { std::cout << arr[i] << "\n"; } 

Range-based loops are entered in order to break free of a variable, which is usually not needed when outputting array values. Using a variable to store indexes is often the cause of numerous errors either when the indexing is not started from 0, but from, for example, 1, or when the upper value of the index range is incorrect.

    In addition to the @Vlad from Moscow full answer - for the case of using other containers, please note that the concept of indexes does not apply to all containers. So the output method, for example,

     int arr[3] = { 9, 7, 1 }; int i = 0; for (auto n: arr) { std::cout << "arr[" << i++ << "] = " << n << "\n"; } 

    Which in principle works for arrays or vectors (and is not sure if this standard guarantees), is not suitable for many containers - for example, for hash tables, the order of placement is not defined at all, for sets - they are always ordered.

    • in addition to the built-in array and std :: vector, indexing can also be used for std :: deque - a sequential container storing data in blocks of k elements forming a linked list - ampawd