why are these two ways of accessing parts of C++ map pairs different

98 Views Asked by At

I was puzzled when I received an error that suggested I use a . operator to access the value in a pair from a map because when I changed it in two places in code I received a new error that suggested that I use a -> in the second place in code. I listened to the naggy compiler. Why did I need to?

Here's what I was doing:

In a range based for loop, I want the value from the key-value pair which could be exampled:

std::map<std::string, aclass> mapthings;
...
for (auto& it : mapthings) {
    fout << it.second.stringify();
}

I'm also using the same mapthings but using the find() function:

return (mapthings.find(name))->second;
5

There are 5 best solutions below

1
On BEST ANSWER

In this code snippet

std::map<std::string, aclass> mapthings;
...
for (auto& it : mapthings) {
    fout << it.second.stringify();
}

it is of type value_type of std::map<std::string, aclass> that corresponds to type

std::pair<const std::string, aclass>

So to access members of an object of this type you have to use operator .

In this code snippet

return (mapthings.find(name))->second;

method find returns iterator that points to the target record of the map or to iterator returned by end(). Iterators are like pointers. So you need to use operator -> to access members of the pointed object.

Take into account that you could write simpler

return mapthings.find( name )->second;

or

return ( *mapthings.find( name ) ).second;
0
On

When you use this code, you get a reference to a std::pair containing your data

for (auto& it : mapthings) {
    fout << it.second.stringify();
}

In the second example, find returns an iterator which needs to be dereferenced to be read

0
On

Because find return mapthings::iterator,which stores a pointer to mapthings::value_type. While auto& it is a object of mapthings::value_type.

0
On

In the first example range-based for loop gives object directly. So you can use .. In the second example find gives you iterator to the object. That compels you to use -> because you need object itself.

0
On

In the first one, you get a std::map::value_type&, which is defined to be std::pair<const Key, T>. This method is best for accessing all the members of the map.

In the second one, you get a std::map::iterator. std::map::iterator has operator-> overloaded, which returns a std::map::value_type*. This method is best for find, upper_bound, lower_bound, etc. since you are performing queries on the map. The map might not hold a member corresponding to the key used in the query.