std::map и operator []

Тема в разделе "LANGS.C", создана пользователем _DEN_, 30 май 2007.

  1. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    В Comeau и MSVC 8.0 у std::map нету const версии оператора [].

    Код (Text):
    1. #include <map>
    2.  
    3. int foo(const std::map<int, int>& m, int key)
    4. {
    5.     return m[key];
    6. }
    7.  
    8. int main()
    9. {
    10.     std::map<int, int> m;
    11.     m[1] = 10;
    12.     int x = foo(m, 1);
    13.  
    14.     return 0;
    15. }
    Это нормально?
     
  2. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    _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."
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    q_q

    Что в данномконтексте значит Afaik? :)

    А перегрузку по const-признаку уже отменили?
     
  4. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    _DEN_
    Она ничего не даст - ведь если элемент не будет найден, то, следуя философии/реализации map, будет добавлен новый элемент, а значит, map должна быть изменена при этом.
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    IceStudent

    Какой еще философии? Перегрузка по const-признаку для того и придумана, чтобы предоставить два варианта функций, модифицирующий, который можно применять только с неконстнтными объектами, и не модифицирующий, который можно применять с любыми объекрами.
     
  6. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    _DEN_
    Что в данномконтексте значит Afaik? :)
    Эту аббревиатуру использую, если не уверен, что ответ полностью снимет вопрос.
    Я не специалист по использованию С++ & STL, полагал, что цитаты Stroustrup'а может оказаться не достаточно. Ты уже начал задавать "хитрые" вопросы. :) В ответе на него солидарен с IceStudent.
     
  7. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Ещё раз: для константного вызова есть find. А вызывая [], нельзя быть уверенным, что элемент есть, а [] ведь должен что-то возвращать.
     
  8. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    "As Far As I Know" (англ.) = "насколько я знаю"
    а откуда ты знаешь что не придется модифицировать
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    IceStudent

    std::out_of_range спасет мир.
    Кроме того - можно разыменовывать end(). Это вызовет вполне законную рантаймовую ошибку.

    Great

    По константности объекта.
     
  10. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    _DEN_
    А ты заметил, когда это исключение вызывается? Во всяких at, а в [] оно никогда не вызывается, что сделано для быстроты и удобства. Так и в map: никаких исключений в [], а для доступа с проверкой есть find() и lower_bound().
     
  11. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    IceStudent

    Ну [] у мапа все же не такой как у вектора. Ну да ладно - почему бы [] не возвращать end если ничего не найдено?
     
  12. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    _DEN_
    end() - возвращает итератор
    [] - возвращает ссылку
    ;)
     
  13. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    maxdiver

    Опять ты? :)) [] const мог бы работать как возвращатель разыменованного find().
     
  14. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    _DEN_
    Ну, собственно, не-const-версия примерно так и работает.
    А вот в const-версии, если элемента нет, то произошли бы Очень Плохие Вещи :)
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    maxdiver

    Какие?

    Код (Text):
    1. const TValue& map<TKey, TValue>::opetator [] (const TKey& key) const
    2. {
    3.     return find(key)->second;
    4. }
     
  16. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    _DEN_
    Чей second хочешь получть, если нет first == key?
     
  17. maxdiver

    maxdiver Max

    Публикаций:
    0
    Регистрация:
    18 июл 2006
    Сообщения:
    308
    Адрес:
    Саратов
    Разыменование указателя, указывающего неизвестно куда.
    operator* не обязан проверять валидность операции, проверки выполняются только в виде Debug'а.
    ИМХО operator* даже _обязан_ не генерировать исключений
     
  18. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    q_q

    Хочу получить ошибку, не важно в каком виде.
     
  19. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    _DEN_
    Придется писать свой map.

    У меня создалось впечатление, что тебя загипнотизировали квадратные скобки, и ты считаешь, что можешь использовать operator[] для доступа к элементам контейнера, как к элементам массива. Вот что пишет Скот Мейерс в "Эффективное использование STL" (Глава 3. Ассоциативные контейнеры. Совет 24. Тщательно выбирайте между map::operator[] и map::insert.): "Функция operator[] контейнеров map ни как не связана ... со встроенным оператором [ ], работающим с массивами. Функция map::operator[] упрощает операции «обновление с возможным созданием»."

    maxdiver
    ИМХО operator* даже _обязан_ не генерировать исключений
    Можно ли добиться этого на практике? Интересно почитать об этом подробнее. Можешь дать ссылку на источник?
     
  20. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    q_q
    Хм, а почему "Функция operator[] контейнеров map ни как не связана ... со встроенным оператором [ ], работающим с массивами"? Ведь в map это тоже доступ к произвольному элементу. Просто он работает по аналогии с динамическим массивом, наращивая его, если запрашиваемого элемента не оказалось. Или я ошибаюсь?