Почему оператор [] не является const для карт STL?


надуманный пример, ради вопроса:

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map[x] << std::endl
}

это не будет компилироваться, так как оператор [] не является const.

это прискорбно, так как синтаксис [] выглядит очень чистым. Вместо этого, я должен сделать что-то вроде этого:

void MyClass::MyFunction( int x ) const
{
  MyMap iter = m_map.find(x);
  std::cout << iter->second << std::endl
}

это всегда меня раздражало. Почему оператор [] не является const?

6 77

6 ответов:

на std::map и std::unordered_map,operator[] вставить значение индекса в контейнер, если он не существует. Это немного неинтуитивно, но так оно и есть.

поскольку он должен быть разрешен для сбоя и вставки значения по умолчанию, оператор не может быть использован на const экземпляр контейнера.

http://en.cppreference.com/w/cpp/container/map/operator_at

теперь, когда с C++11 вы можете иметь более чистую версию с помощью at ()

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map.at(x) << std::endl;
}

Примечание для новых читателей.
Исходный вопрос был о контейнерах STL (не конкретно о std::map)

следует отметить, что на большинстве контейнеров существует const-версия operator [].
Просто std::map и std:: set не имеют версии const, и это результат базовой структуры, которая их реализует.

от std:: vector

reference       operator[](size_type n) 
const_reference operator[](size_type n) const 

также для вашего второго примера вы должны проверить, не удалось ли найти элемент.

void MyClass::MyFunction( int x ) const
{
    MyMap iter = m_map.find(x);
    if (iter != m_map.end())
    {
        std::cout << iter->second << std::endl
    }
}

поскольку оператор [] может вставить новый элемент в контейнер, он не может быть функцией-членом const. Обратите внимание, что определение оператора[] чрезвычайно просто: m[k] эквивалентно (*((m.insert(value_type(k, data_type()))).сначала.))второй. Строго говоря, эта функция-член не нужна: она существует только для удобства

оператор индекса должен быть только const для контейнера только для чтения (который на самом деле не существует в STL per se).

операторы индекса используются не только для просмотра значений.

Если вы объявите переменную-член std::map изменяемой

mutable std::map<...> m_map;

вы можете использовать неконстантные функции-члены std::map в ваших функциях-членах const.