Patrick Donnelly
Patrick Donnelly

Reputation: 43

std::map::const_iterator leaks non-const reference to value?

I've observed that a std::map::const_iterator leaks a non-const reference to the value_type:

#include <map>
#include <stdio.h>

int main (int argc, char *argv[])
{
  std::map<int,int> foo = {{1,1},{4,2}};
  const auto &m = foo;
  const auto &it = foo.find(1);
  printf("%d %d\n", it->first, it->second);
  int &i = it->second;
  i = 3;
  auto &one = foo.at(1);
  printf("%d %d\n", 1, one);
  return 0;
}

outputs

$ g++ test.cc && ./a.out 
1 1
1 3

Is this expected? Why? Is the only way to codify const-protection of the std::map is to wrap it in another class?

Upvotes: 4

Views: 630

Answers (1)

Slava
Slava

Reputation: 44288

This line:

const auto &it = foo.find(1);

creates const reference to std::map<int,int>::iterator named it, so you cannot modify it itself or iterator it refers to, but can modify data it points to (as iterator). It is similar to constant pointer vs pointer to const data. Use m to get std::map<int,int>::const_iterator with type auto deduction (it does not have to be const reference) or give it explicit type:

std::map<int,int>::const_iterator it = foo.find(1);

then you cannot modify data through that iterator.

Upvotes: 7

Related Questions