2
  void example(const map<string, vector<int> > & num);

  int main()
  {
      map<string, vector<int> >num;

      num["A"].push_back(1);
      example(num);

      return 0;
  }

  void example(const map<string, vector<int> > & num)
  {
      cout <<  num["A"].size() << endl;
  }

i think the size() did not change the value of num, but why it cause error when complie it? it's ok when i removed the keyword const in the example function.

Zik
  • 202
  • 3
  • 11

4 Answers4

2

The problem isn't the call to size(). The problem is using operator[]() on a const map: if the key doesn't exist, the subscript operator would insert the key and, hence, modify the map. To do so, the std::map<std::string, std::vector<int>> can't be const, of course.

If you just want to access the values you'll need to use find() directly:

void example(std::map<std::string, std::vector<int>> const& num) {
    std::map<std::string, std::vector<int>>::const_iterator it(num.find("A"));
    if (it != num.end()) {
        std::cout << it->second.size() << '\n';
    }
    else {
        std::cout << "No key 'A` in the map\n";
    }
}

... or you can use at() which will throw an exception when accessing a key which isn't present on a non-const map (thanks to bamboon for pointing at this question):

void example(std::map<std::string, std::vector<int>> const& num) {
    std::cout << num["A"].size() << '\n';
}
Community
  • 1
  • 1
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
1

The problem is that operator [] is not defined for const objects of type std::map. Here are declarations of the operator

T& operator[](const key_type& x);
T& operator[](key_type&& x);

As you see the qualifier const after the closing parenthesis of the parameter list is absent. However member function at is defined for const objects (see the second declaration)

T& at(const key_type& x);
const T& at(const key_type& x) const;.

So instead of the subscript operator you must use member function at.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

The function num doesn't know that there is a key "A" already added in another function and, if there weren't one, num["A"] would add it. Therefore, to use [], the map operand cannot be const.

In short, it's not size()'s fault.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

Others pointed out what's the problem. What you could do now is e.g.

  void example(const map<string, vector<int> > & num)
  {
      cout <<  num.at("A").size() << endl;
  }

which would be a little bit slower.

Sceptical Jule
  • 889
  • 1
  • 8
  • 26
  • Why would it be slower ? – Matthieu M. Dec 28 '13 at 13:42
  • Because this function performs range checks. See http://stackoverflow.com/questions/3269809/stdvectorat-vs-operator-surprising-results-5-to-10-times-slower-f – Sceptical Jule Dec 28 '13 at 13:46
  • `std::map::operator[]` also needs some more logic and checks because it might need to construct the element. – Stephan Dollberg Dec 28 '13 at 13:57
  • @ScepticalJule: I am afraid you did not understand how `at` works on a **map**. There is no concept of range-check on a map: since this is an access by key both `[]` and `at` have to search for the key and decide what to do depending on its presence or absence anyway. Therefore, it is **unlikely** to be slower when the key is present. In its absence... well the two of them do things that are so different it matters little which is slower. – Matthieu M. Dec 28 '13 at 14:07