std::map + insert вопрос.
От: IROV..  
Дата: 30.09.05 20:57
Оценка: :)
стандартная функция добавление в мапу..

void insert_resource(const std::string &Key, const T &Value)
{
 TMap::iterator it_find = m_MapRes.find(Key);

 if( it_find != m_MapRes.end() )
 {
  return;
 }

 m_MapRes.insert(std::make_pair(Key,Value));
}


надеюсь не опечатался..

думаю не раз мы видели такую конструкцию кода...

вот сейчас полночь.. и как всегда бред лезет в голову..

что если эту функцию заменить на..


void insert_resource(const std::string &Key, const T &Value)
{
 TMap::iterator it_find = m_MapRes.lower_bound(Key);
 
 if( it_find != m_MapRes.end() && it->first == key )
 {
  return;
 }

 m_MapRes.insert(it_find,std::make_pair(Key,Value));
}



Как мне кажеться это будет работать быстрее.. или я чтото пропустил..

возможно что даже и работать не будет..(Хотя и написал тест прогу... работала)
я не волшебник, я только учусь!
Re: std::map + insert вопрос.
От: Анатолий Широков СССР  
Дата: 30.09.05 21:07
Оценка:
А в чем выигрыш?

И вообще, если позволяет задача, все эти "телодвижения" можно выразить более кратко:

map[key] = value;
Re[2]: std::map + insert вопрос.
От: IROV..  
Дата: 30.09.05 21:23
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>А в чем выигрыш?


расмотрим первый вариант

TMap::iterator it_find = m_MapRes.find(Key);

вызываем поиск +

если не нашли.. то!

m_MapRes.insert(std::make_pair(Key,Value));

тут мы опять ишем итератор..

есле же мы сначало найдем итератор предшественик.. то тогда мы можем не искать ключ и вызвать инсерт жорсткий..

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

АШ>И вообще, если позволяет задача, все эти "телодвижения" можно выразить более кратко:


АШ>
АШ>map[key] = value;
АШ>


не спорю.
я не волшебник, я только учусь!
Re[3]: std::map + insert вопрос.
От: Анатолий Широков СССР  
Дата: 30.09.05 21:38
Оценка:
Да, конечно, подсказка insert-у — уже не вижу, пора спать. Но, почему бы не использовать в этом случае просто insert? Взгляните:


pair <iterator, bool> insert(
   const value_type& _Val
);



Чтобы проверить есть элемент или нет достаточно проанализировать second возвращаемой пары:

std::map<int, std::string> m;
p = m.insert(std:make_pair(1, std::string("1")));
if( p.second == true )
   std::count << "элемент только что добавлен";


Удачи!
Re[4]: std::map + insert вопрос.
От: IROV..  
Дата: 01.10.05 09:31
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Да, конечно, подсказка insert-у — уже не вижу, пора спать. Но, почему бы не использовать в этом случае просто insert? Взгляните:



АШ>
АШ>pair <iterator, bool> insert(
АШ>   const value_type& _Val
АШ>);
АШ>



АШ>Чтобы проверить есть элемент или нет достаточно проанализировать second возвращаемой пары:


АШ>
АШ>std::map<int, std::string> m;
АШ>p = m.insert(std:make_pair(1, std::string("1")));
АШ>if( p.second == true )
АШ>   std::count << "элемент только что добавлен";
АШ>


АШ>Удачи!

Это конечно лучше чем первый вариант.. но всеже это не совсем хорошо.. а имено..

зачем мы делаем insert вместо operator [] .. думаю для того что бы не конструировать лишний раз std::pair
в твоем варианте мы всеже вызовем конструктор у Key а также у Value
Если Value довольно громозкий то будет беда..

в моемже случаее мы не будем вызывать конструктор..
я не волшебник, я только учусь!
Re[2]: std::map + insert вопрос.
От: Alny Украина  
Дата: 01.10.05 15:43
Оценка:
АШ>И вообще, если позволяет задача, все эти "телодвижения" можно выразить более кратко:

АШ>
АШ>map[key] = value;
АШ>


Нельзя. Логика ранее приведенного кода такая: если в map уже содержиться пара (key1, value1) и идет попытка вставить (key1, value2), то последняя пара втавлена не будет.
В этом же коде данная пара вставлена будет.
Re[2]: std::map + insert вопрос.
От: pavel_turbin  
Дата: 01.10.05 17:08
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>А в чем выигрыш?


АШ>И вообще, если позволяет задача, все эти "телодвижения" можно выразить более кратко:


АШ>
АШ>map[key] = value;
АШ>


IMHO, может возникнуть ненужное копирование, если об'ект уже существует.
Re[3]: std::map + insert вопрос.
От: Анатолий Широков СССР  
Дата: 01.10.05 18:01
Оценка:
Здравствуйте, Alny, Вы писали:

АШ>>И вообще, если позволяет задача, все эти "телодвижения" можно выразить более кратко:


АШ>>
АШ>>map[key] = value;
АШ>>


A>Нельзя. Логика ранее приведенного кода такая: если в map уже содержиться пара (key1, value1) и идет попытка вставить (key1, value2), то последняя пара втавлена не будет.

A> В этом же коде данная пара вставлена будет.

Это не multimap, поэтому ни о какой вставке речи быть не может, если значение ключа уже присутствует в ассоциативном контейнере. Значение ассоциированное с ключем просто обновится и в некоторых случаях это то, что нужно.
Re[3]: std::map + insert вопрос.
От: Анатолий Широков СССР  
Дата: 01.10.05 18:02
Оценка:
Здравствуйте, pavel_turbin, Вы писали:

_>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>А в чем выигрыш?


АШ>>И вообще, если позволяет задача, все эти "телодвижения" можно выразить более кратко:


АШ>>
АШ>>map[key] = value;
АШ>>


_>IMHO, может возникнуть ненужное копирование, если об'ект уже существует.


Согласен, поэтому и написал "если позволяет задача"
Re[4]: std::map + insert вопрос.
От: Alny Украина  
Дата: 03.10.05 08:25
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Это не multimap, поэтому ни о какой вставке речи быть не может, если значение ключа уже присутствует в ассоциативном контейнере. Значение ассоциированное с ключем просто обновится и в некоторых случаях это то, что нужно.


Я имел в виду то, что первый и второй алгоритмы работают по разному, чему как доказательство следующий код
#include <map>
#include <string>
using namespace std;

typedef int T;
typedef map<string, T> TMap;
TMap m_MapRes;

void insert_resource(const std::string &Key, const T &Value)
{
    TMap::iterator it_find = m_MapRes.find(Key);

    if( it_find != m_MapRes.end() )
    {
        return;
    }
    m_MapRes.insert(std::make_pair(Key,Value));
}

int _tmain(int argc, _TCHAR* argv[])
{
    //инициируем map
    m_MapRes["test1"] = 1;
    m_MapRes["test2"] = 2;

    //1й вариант c insert_resource
    insert_resource( "test2", 3 );
    cout << m_MapRes["test2"] << endl;
    //2й вариант c []
    m_MapRes["test2"] = 3;
    cout << m_MapRes["test2"] << endl;
    return 0;
}

Как и следовало ожидать выдадут
2
3
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.