454

I want to iterate through each element in the map<string, int> without knowing any of its string-int values or keys.

What I have so far:

void output(map<string, int> table)
{
       map<string, int>::iterator it;
       for (it = table.begin(); it != table.end(); it++)
       {
            //How do I access each element?  
       }
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
NoName
  • 9,824
  • 5
  • 32
  • 52
  • 4
    Possible duplicate of [How to loop through a c++ map](http://stackoverflow.com/questions/4844886/how-to-loop-through-a-c-map) – amanuel2 Apr 26 '16 at 01:06
  • 2
    you most probably don't want the function to get the map by value, would be better to get it as `const map& table` – Amir Kirsh Sep 20 '20 at 19:59

8 Answers8

942

You can achieve this like following :

map<string, int>::iterator it;

for (it = symbolTable.begin(); it != symbolTable.end(); it++)
{
    std::cout << it->first    // string (key)
              << ':'
              << it->second   // string's value 
              << std::endl;
}

With C++11 ( and onwards ),

for (auto const& x : symbolTable)
{
    std::cout << x.first  // string (key)
              << ':' 
              << x.second // string's value 
              << std::endl;
}

With C++17 ( and onwards ),

for (auto const& [key, val] : symbolTable)
{
    std::cout << key        // string (key)
              << ':'  
              << val        // string's value
              << std::endl;
}
jaba
  • 735
  • 7
  • 18
P0W
  • 46,614
  • 9
  • 72
  • 119
  • 13
    add the "auto" type in front of "it" – iedoc Apr 03 '15 at 13:41
  • 5
    @P0W Why "auto const&" for C++11 but "const auto&" for C++17? Any difference between "auto const&" and "const auto&"? – Eric Jun 02 '17 at 02:26
  • 65
    There is no difference, it's just a matter of taste. However it seems like @P0W 's taste is not very conistent... – Kapichu Jul 06 '17 at 20:16
  • 31
    Thanks for updating with the C++17 one, I was looking for the `auto const& [key, val] : symbolTable` format! – Water Mar 05 '18 at 01:49
  • @P0W C++ 17 example is not working in VS2017, what is the problem? – molamola Aug 15 '18 at 03:49
  • @haram the feature might not be implemented yet in the version of visual studio 2017 compiler you're using. – P0W Aug 15 '18 at 05:28
  • then how can I test that feature? gcc? – molamola Aug 20 '18 at 04:01
  • 4
    @haram You might have to set "ISO C++17 Standard (/std:c++17)" in the project settings (Configuration Properties > C/C++ > Language > C++ Language Standard) – Swordfish Aug 31 '18 at 05:57
  • 1
    doesn't have to be "auto const&" BTW; can be "auto&" if you wish to mutate – Den-Jason Jan 20 '20 at 16:36
  • 1
    From [cppreference](https://en.cppreference.com/w/cpp/language/reference#Forwarding_references), a forwarding reference is the safest way to use range for loops: `for (auto&& x: f())` – Julian Jan 31 '20 at 11:06
  • 1
    @Eric • just remember the rule `const` always binds to the thing to its immediate left, unless it is first in which case it binds to the thing to its immediate right. (If you always do it the first way, you won't have to think about the exception. If you always do it the special case latter way when possible, then you have to think hard when you see the general way.) – Eljay Mar 22 '20 at 19:20
  • One could also use `BOOST_FOREACH`. – stephanmg Aug 18 '20 at 13:27
  • 'Structured bindings' is what MSVC refers to the C++17 language feature as. – Fredrick Mar 03 '21 at 14:45
  • @Eric, `const` always refers to its left. if there's nothing there, then refers to its right. – Vassilis May 20 '21 at 05:26
  • 1
    Any reason why "auto const&" is used? As it's fine with just "auto". – Ashutosh Tiwari Oct 29 '21 at 18:39
  • It's better to use pre-increment for your iterators. – Pan P Dec 24 '21 at 10:36
38

Try the following

for ( const auto &p : table )
{
   std::cout << p.first << '\t' << p.second << std::endl;
} 

The same can be written using an ordinary for loop

for ( auto it = table.begin(); it != table.end(); ++it  )
{
   std::cout << it->first << '\t' << it->second << std::endl;
} 

Take into account that value_type for std::map is defined the following way

typedef pair<const Key, T> value_type

Thus in my example p is a const reference to the value_type where Key is std::string and T is int

Also it would be better if the function would be declared as

void output( const map<string, int> &table );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
14

The value_type of a map is a pair containing the key and value as it's first and second member, respectively.

map<string, int>::iterator it;
for (it = symbolTable.begin(); it != symbolTable.end(); it++)
{
    std::cout << it->first << ' ' << it->second << '\n';
}

Or with C++11, using range-based for:

for (auto const& p : symbolTable)
{
    std::cout << p.first << ' ' << p.second << '\n';
}
Columbo
  • 60,038
  • 8
  • 155
  • 203
11

As @Vlad from Moscow says, Take into account that value_type for std::map is defined the following way:

typedef pair<const Key, T> value_type

This then means that if you wish to replace the keyword auto with a more explicit type specifier, then you could this;

for ( const pair<const string, int> &p : table ) {
   std::cout << p.first << '\t' << p.second << std::endl;
} 

Just for understanding what auto will translate to in this case.

John Mutuma
  • 3,150
  • 2
  • 18
  • 31
11

As P0W has provided complete syntax for each C++ version, I would like to add couple of more points by looking at your code

  • Always take const & as argument as to avoid extra copies of the same object.
  • use unordered_map as its always faster to use. See this discussion

here is a sample code:

#include <iostream>
#include <unordered_map>
using namespace std;

void output(const auto& table)
{
   for (auto const & [k, v] : table)
   {
        std::cout << "Key: " << k << " Value: " << v << std::endl;
   }
}

int main() {
    std::unordered_map<string, int> mydata = {
        {"one", 1},
        {"two", 2},
        {"three", 3}
    };
    output(mydata);
    return 0;
}
Mital Vora
  • 2,199
  • 16
  • 19
  • can you explain, how multiple copies of same object can get created if we don't use const& ? Is there any edge condition when it can happen? – Ashutosh Tiwari Oct 29 '21 at 18:42
  • 1
    @AshutoshTiwari its the reference of the variable `&` which avoids creating the multiple copies and when we take the reference, we do not want it to be modified hence we use `const` – Mital Vora Nov 02 '21 at 11:49
3

it can even be done with a classic for loop.
advancing the iterator manually.

typedef std::map<int, int> Map;

Map mymap;

mymap['a']=50;
mymap['b']=100;
mymap['c']=150;
mymap['d']=200;

bool itexist = false;
int sizeMap = static_cast<int>(mymap.size());
auto it = mymap.begin();
for(int i = 0; i < sizeMap; i++){
    std::cout << "Key: " << it->first << " Value: " << it->second << std::endl;
    it++;
}
NaturalDemon
  • 934
  • 1
  • 9
  • 21
3

if you just want to iterate over the content without changing values do:

for(const auto & variable_name : container_name(//here it is map name)){
    cout << variable_name.first << " : " << variable_name.second << endl; 
} 

If you want to modify the contents of the map, remove the const and keep & (if you want to modify directly the contents inside container). If you want to work with a copy of the container values, remove the & sign too; after that, you can access them by using .first and .second on "variable_name".

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
1

Other way :

map <int, string> myMap = {
    { 1,"Hello" },
    { 2,"stackOverflow" }
};
for (auto iter = cbegin(myMap); iter != cend(myMap); ++iter) {
    cout << iter->second << endl;
}
N.Omar
  • 29
  • 6
  • 2
    [A code-only answer is not high quality](https://meta.stackoverflow.com/questions/392712/explaining-entirely-code-based-answers). While this code may be useful, you can improve it by saying why it works, how it works, when it should be used, and what its limitations are. Please [edit] your answer to include explanation and link to relevant documentation. – Muhammad Mohsin Khan Mar 13 '22 at 11:05