Search code examples
c++standard-library

Assigning to a map iterator causes value change without being a reference


I don't understand why assigning to an iterator->second in a std::map modifies the value into the map

#include <typeinfo>
#include <map>
#include <iostream>

int main() {
  std::map<int, int> lol;
  lol[2] = 33;

  auto it = lol.find(2);

  it->second = 91; // This changes the map's value

  std::cout << typeid(it->second).name(); // This just shows 'int', not a reference

  std::cout << lol[2]; // 91

  return 0;
}

isn't it->second just an int and not a reference?


Solution

  • isn't it->second just an int and not a reference?

    Yes, it is just an int. *it gives you a std::pair<int const, int>&, a reference to the actual value of the node in the map. But the member access to second is in fact just an int. The trait "is a reference" and the trait "is assignable to" are not equivalent - you can assign to non-references, and there are references you can't assign to. it->second gives you an lvalue of type int, that you can assign through, in the same way that:

    int i = 4;
    i = 5; // i is not a reference, but you can assign it here
    

    That said, typeid() wouldn't give you a reference type anyway because reference and cv-qualifications are dropped from type analysis. See also my answer here.

    That said, what you probably want to look at is decltype((it->second)) (yes, double the parentheses, double the fun). This, in fact, gives you int&, because that expression is an lvalue of type int.