map::insert

Тема в разделе "LANGS.C", создана пользователем cupuyc, 5 авг 2011.

  1. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    Не совсем понимаю как работает метод
    Код (Text):
    1. iterator map::insert(
    2.    iterator _Where,
    3.    const value_type& _Val
    4. );
    В MSDN написано:
    Но при вставке я обнаруживаю вызов оператора сравнения аж 14 раз, хотя, итератор указывает непосредственно на вставляемый элемент. Тут ведь даже дерево балансировать не нужно!
    Код (Text):
    1. class A
    2. {
    3. private:
    4.   int x;
    5.  
    6. public:
    7.   A(int x) : x(x) {}
    8.  
    9.   inline bool operator < (A const& a) const
    10.   {
    11.     return x < a.x;
    12.   }
    13. };
    14.  
    15. int test()
    16. {
    17.   std::map<A, char> m;
    18.   std::map<A, char>::iterator i;
    19.  
    20.   for (uint_t i = 0; i < 100; ++ i)
    21.   {
    22.     m[i] = 'a' + i % ('z' - 'a');
    23.   }
    24.  
    25.   i = m.lower_bound(2); // operator < calls 16 onces
    26.   m.insert(i, std::map<int, char>::value_type(2, 'e')); // operator < calls 14 onces
    27.  
    28.   return 0;
    29. }
    Почему так?
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Хм, а зачем вообще нужен такой инсерт?
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Спасибо, поржал )
     
  4. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    Потому что ты пытаешься вставить в map элемент, который там уже есть - смотри первый цикл.
     
  5. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    И что? Он должен сравнить элемент с двумя соседними вершинами, а не пробегать заново всё дерево..

    Если я уже знаю позицию, то вставка будет происходить быстрее, не находите?
     
  6. _DEN_

    _DEN_ DEN

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

    А если в этой позиции будет нарушаться алфавитный порядок ключа?
     
  7. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    cupuyc
    Это библиотечная реализация. Она считает, что клиентский код написан идиотом. Посему единственный метод вставить без лишних проверок -- это забить на инкапсуляцию и врезать самостоятельно. Что, как правило, не вариант.
    Есть ещё один способ: написать этот самый map ручками. Это ведь бинарное отсортированное дерево? Ну дык его писать -- двадцать минут вместе с отладкой и тестами.
     
  8. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    cupuyc
    В таком случае, скорее всего, не совсем правильно задается позиция для вставки. Пробегись отладчиком, благо исходники STL имеются.

    r90
    map обычно реализуется красно-черным деревом, это далеко не на 20 минут реализации.
     
  9. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    Значит будет значительно дольше, я так предполагаю. Пробежится пио дереву вниз, не найдёт, начнёт с корня.

    Не совсем. Это красно-чёрное дерево. Вставка/удаление элементов - не так тривиальны.

    Я пробовал и ++ к позиции делать и --. Разница есть, но не большая.
     
  10. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    ещё такой прикол:

    Код (Text):
    1.   std::map<int, int> m;
    2.   std::map<int, int>::iterator i;
    3.   m.insert(std::map<int, int>::value_type(1, 'a'));
    4.   i = m.begin(); // i = (1, 'a')
    5.   -- i; // i = m.end()
    6.   -- i; // i = (1, 'a')
    7.   -- i; // i = m.end()
    8.   -- i; // i = (1, 'a')
    то есть если на iterator равный end сделать декремент, то iterator указывает на первый элемент.
     
  11. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    cupuyc
    А ты не парься и напиши тривиальную реализацию. Когда (и если) понадобится нетривиальная, потратишь пару суток и напишешь её.
     
  12. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    r90
    Вообще-то std либа написана нормально, не на все случаи конечно. Для чего вы предлагаете написание велосипеда?
     
  13. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Один как обычно пытается дискредитировать стандартную библиотеку, другой предлагает её выкинуть. Мой вопрос был с подколкой, дискутировать о велосипедах и прочих транспортах в мои планы не входило.
     
  14. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Booster
    Я ничего не говорил о "нормальности" или "ненормальности" stl. Просто если вставить в универсальную реализацию дерева дольше и сложнее, чем написать узкоспециализированный велосипед, то я голосую за велосипед.
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Лол, тоже мне истина в последней инстанции.

    А про велосипеды и несовершенство STL - пожалуйста, продолжайте. Это так увлекательно ^_^
     
  16. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Как обычно перед тем как катить бочку нужно хорошо почитать мануал.
    То есть элемент тупо не вставляется и всё, значение конечно не меняется. Если элемент не был до этого вставлен, то данная версия функции работает как и ожидается(кто бы сомневался). Единственно к чему тут можно придраться, так это почему в случае обнаружения совпадения функция не вышла сразу, а запускается поиск с корня. Но вот такая реализация, сэкономили на дополнительных проверках, стандарту это не противоречит.

    Производить операции над end - запрещено, это ub.
     
  17. _DEN_

    _DEN_ DEN

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

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    r90
    Надо просто правильно использовать инструмент.
     
  19. Atlantic

    Atlantic Member

    Публикаций:
    0
    Регистрация:
    22 июн 2005
    Сообщения:
    322
    Адрес:
    Швеция
    stl надежна и проверена временем, разрабатывалась с упором на эффективность, и при правильном применении как минимум не хуже велосипедов, а зачастую гораздо лучше. Что кстати понимается под "практическим софтом"? В проекте масштаба ~500k строк и ~2 лет разработки тоже не будете использовать stl, boost и прочие библиотеки?
     
  20. r90

    r90 New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2005
    Сообщения:
    898
    Booster
    Ну так и я о том же. Если мы собираемся использовать инструмент так, как нельзя использовать map, значит нам нужен другой инструмент.