В Comeau и MSVC 8.0 у std::map нету const версии оператора []. Код (Text): #include <map> int foo(const std::map<int, int>& m, int key) { return m[key]; } int main() { std::map<int, int> m; m[1] = 10; int x = foo(m, 1); return 0; } Это нормально?
_DEN_ Это нормально? Afaik да. Цитата из "The C++ Programming Language Third Edition. Bjarne Stroustrup" конец параграфа 17.4.1.3: "Subscripting a map adds a default element when the key is not found. Therefore, there is no version of operator[]() for const maps. Furthermore, subscripting can be used only if the mapped_type (value type) has a default value. If the programmer simply wants to see if a key is present, the find() operation (§17.4.1.6) can be used to locate a key without modifying the map."
_DEN_ Она ничего не даст - ведь если элемент не будет найден, то, следуя философии/реализации map, будет добавлен новый элемент, а значит, map должна быть изменена при этом.
IceStudent Какой еще философии? Перегрузка по const-признаку для того и придумана, чтобы предоставить два варианта функций, модифицирующий, который можно применять только с неконстнтными объектами, и не модифицирующий, который можно применять с любыми объекрами.
_DEN_ Что в данномконтексте значит Afaik? Эту аббревиатуру использую, если не уверен, что ответ полностью снимет вопрос. Я не специалист по использованию С++ & STL, полагал, что цитаты Stroustrup'а может оказаться не достаточно. Ты уже начал задавать "хитрые" вопросы. В ответе на него солидарен с IceStudent.
Ещё раз: для константного вызова есть find. А вызывая [], нельзя быть уверенным, что элемент есть, а [] ведь должен что-то возвращать.
IceStudent std::out_of_range спасет мир. Кроме того - можно разыменовывать end(). Это вызовет вполне законную рантаймовую ошибку. Great По константности объекта.
_DEN_ А ты заметил, когда это исключение вызывается? Во всяких at, а в [] оно никогда не вызывается, что сделано для быстроты и удобства. Так и в map: никаких исключений в [], а для доступа с проверкой есть find() и lower_bound().
IceStudent Ну [] у мапа все же не такой как у вектора. Ну да ладно - почему бы [] не возвращать end если ничего не найдено?
_DEN_ Ну, собственно, не-const-версия примерно так и работает. А вот в const-версии, если элемента нет, то произошли бы Очень Плохие Вещи
maxdiver Какие? Код (Text): const TValue& map<TKey, TValue>::opetator [] (const TKey& key) const { return find(key)->second; }
Разыменование указателя, указывающего неизвестно куда. operator* не обязан проверять валидность операции, проверки выполняются только в виде Debug'а. ИМХО operator* даже _обязан_ не генерировать исключений
_DEN_ Придется писать свой map. У меня создалось впечатление, что тебя загипнотизировали квадратные скобки, и ты считаешь, что можешь использовать operator[] для доступа к элементам контейнера, как к элементам массива. Вот что пишет Скот Мейерс в "Эффективное использование STL" (Глава 3. Ассоциативные контейнеры. Совет 24. Тщательно выбирайте между map::operator[] и map::insert.): "Функция operator[] контейнеров map ни как не связана ... со встроенным оператором [ ], работающим с массивами. Функция map::operator[] упрощает операции «обновление с возможным созданием»." maxdiver ИМХО operator* даже _обязан_ не генерировать исключений Можно ли добиться этого на практике? Интересно почитать об этом подробнее. Можешь дать ссылку на источник?
q_q Хм, а почему "Функция operator[] контейнеров map ни как не связана ... со встроенным оператором [ ], работающим с массивами"? Ведь в map это тоже доступ к произвольному элементу. Просто он работает по аналогии с динамическим массивом, наращивая его, если запрашиваемого элемента не оказалось. Или я ошибаюсь?