Доступ к элементу карты const в C ++

101

Я попытался использовать оператор [] для доступа к элементу на карте const C ++, но этот метод не удался. Я также пытался использовать "at ()", чтобы сделать то же самое. На этот раз это сработало. Однако я не смог найти никаких ссылок на использование "at ()" для доступа к элементу в константной карте C ++. Является ли "at ()" новой функцией в карте C ++? Где я могу найти дополнительную информацию об этом? Большое спасибо!

Примером может быть следующее:

#include <iostream>
#include <map>

using namespace std;

int main()
{
        map<int, char> A;
        A[1] = 'b';
        A[3] = 'c';

        const map<int, char> B = A;

        cout << B.at(3) << endl; // it works
        cout << B[3] << endl;  // it does not work

}

Для использования «B [3]» он вернул следующие ошибки во время компиляции:

t01.cpp: 14: ошибка: передача 'const std :: map, std :: allocator>>' в качестве аргумента 'this' в '_Tp & std :: map <_Key, _Tp, _Compare, _Alloc> :: operator [] ( const _Key &) [with _Key = int, _Tp = char, _Compare = std :: less, _Alloc = std :: allocator>] 'отбрасывает квалификаторы

Используемый компилятор - g ++ 4.2.1

ледяная сфера
источник

Ответы:

124

at()это новый метод std::mapв C ++ 11.

Вместо того, чтобы вставлять новый сконструированный элемент по умолчанию, как operator[]если бы элемент с данным ключом не существует, он генерирует std::out_of_rangeисключение. (Это похоже на поведение at()for dequeи vector.)

Из-за такого поведения имеет смысл иметь constперегрузку at(), в отличие от operator[]которой всегда есть возможность изменить карту.

CB Bailey
источник
Возможно ли, чтобы "at" возвращал значение по умолчанию вместо генерации исключения?
user1202136
Я использую at()в VS2013 в проекте, предназначенном для использования инструментария VS2010. Я думал, это означает, что я не использую C ++ 11 ... Но все же он компилируется ... ??
thomthom 07
1
Мне просто нужно прокомментировать, что не имеет смысла опускать оператор const [], который также может вызвать исключение для неотображенного элемента вместо изменения карты.
Спенсер
@Spencer Было бы удивительно, если бы перегрузки оператора [] const и неконстантные имели разные эффекты. Обычно мы ожидаем, что если некоторые неконстантные объекты или ссылки в программе станут константами, программа продолжит вести себя таким же образом, пока она компилируется. Разрешение генерировать исключения только неконстантной перегрузке может привести к ошибкам, которые не будут обнаружены до времени выполнения.
Брайан
@Brian Вы хотели сказать: «Разрешить только перегрузке const вызывать исключения»?
Спенсер
33

Если элемент не существует в a map, operator []он добавит его, что, очевидно, не может работать на constкарте, поэтому C ++ не определяет constверсию оператора. Это хороший пример проверки типов компилятора, предотвращающей потенциальную ошибку времени выполнения.

В вашем случае вам нужно использовать findвместо этого, который будет возвращать только элемент (итератор для), если он существует, он никогда не будет изменять map. Если элемент не существует, он возвращает итератор на карту end().

atне существует и даже не должен компилироваться. Возможно, это «расширение компилятора» (=Жук новое в C ++ 0x).

Конрад Рудольф
источник
Запрещает ли стандарт C ++ реализации определять дополнительные нестандартные функции-члены в библиотечных классах?
Тим Мартин
@ Тим Я считаю, что интерфейс исправлен, да.
Конрад Рудольф
4

[] -Оператор создаст новую запись на карте, если данный ключ не существует. Таким образом, это может изменить карту.

См. Эту ссылку .

Vidstige
источник
2

Для меня это стало большим сюрпризом, но карта STL не имеет constоператора индекса. То есть B[3]не может быть только для чтения. Из руководства:

Поскольку operator [] может вставлять новый элемент в карту, он не может быть константной функцией-членом.

Понятия не имею at().

Бета
источник