Здравствуйте, igna, Вы писали:
I>Здравствуйте, Bell, Вы писали:
B>>Более того, к минусам варианта с insert можно добавить то, что make_pair принимает аргументы и возвращает результат по значению.
I>Кстати, не знаешь, аргументы-то почему по-значению?
Library Defect Report #181
Discussion:
The claim has surfaced in Usenet that expressions such as
make_pair("abc", 3)
are illegal, notwithstanding their use in examples, because template instantiation tries to bind the first template parameter to const char (&)[4], which type is uncopyable.
I doubt anyone intended that behavior...
Proposed resolution:
In 20.2 [utility], paragraph 1 change the following declaration of make_pair():
template <class T1, class T2> pair<T1,T2> make_pair(const T1&, const T2&);
to:
template <class T1, class T2> pair<T1,T2> make_pair(T1, T2);
Здравствуйте, igna, Вы писали:
I>Здравствуйте, ononim, Вы писали:
O>>map::insert вставляет элемент созданный конструктором копирования из указанного, что потенциально быстрее чем создавать объект с дефолтовым конструктором и потом присваивать ему значение
I>Верно, но это не только потенциально быстрее, но и потенциально медленнее, поскольку первый элемент вставляемой пары копируется всегда, в то время как при использовании map::operator[] реализация STL может обойтись без этого копирования.
Согласен, STLPOrt5, например, использует оптимизированную версию. Более того, к минусам варианта с insert можно добавить то, что make_pair принимает аргументы и возвращает результат по значению. Насколько такое копирование критично — зависит от задачи. Если учесть, что в данном случае мы читаем из файла — относительный проигрыш из-за копирований очень сильно зависит от задачи ).
При завершении программы std::map записывается в файл, из которого этот же std::map заполняется при повторном запуске программы. Что вы используете для заполнения, map::insert или map::operator[]?
Здравствуйте, igna, Вы писали:
I>При завершении программы std::map записывается в файл, из которого этот же std::map заполняется при повторном запуске программы. Что вы используете для заполнения, map::insert или map::operator[]?
По крайней мере некоторые распространенные реализации используют тот же самый insert + make_pair в реализации map::operator[]. А поскольку по условию дубликаты в файле отсутствуют, то логичнее сразу же использовать insert — элементы вставляются всегда, "холостых" вызовов make_pair нет.
I>При завершении программы std::map записывается в файл, из которого этот же std::map заполняется при повторном запуске программы. Что вы используете для заполнения, map::insert или map::operator[]?
смотря что мне нужно — безусловное заполнение указанными значениями или с проверкой на существование
если пофиг — использую insert как потенциально более шустрый
Как много веселых ребят, и все делают велосипед...
Здравствуйте, igna, Вы писали:
I>При завершении программы std::map записывается в файл, из которого этот же std::map заполняется при повторном запуске программы. Что вы используете для заполнения, map::insert или map::operator[]?
insert в цикле с результатом предыдущего insert в качестве хинта
I>>При завершении программы std::map записывается в файл, из которого этот же std::map заполняется при повторном запуске программы. Что вы используете для заполнения, map::insert или map::operator[]? B>По крайней мере некоторые распространенные реализации используют тот же самый insert + make_pair в реализации map::operator[]. А поскольку по условию дубликаты в файле отсутствуют, то логичнее сразу же использовать insert — элементы вставляются всегда, "холостых" вызовов make_pair нет.
map::operator[] возвращает ссылку на уже вставленный (конструктором по умолчанию) объект которому потом присваивается (second.operator=) нужное значение
map::insert вставляет элемент созданный конструктором копирования из указанного, что потенциально быстрее чем создавать объект с дефолтовым конструктором и потом присваивать ему значение
Как много веселых ребят, и все делают велосипед...
Здравствуйте, ononim, Вы писали:
O>map::insert вставляет элемент созданный конструктором копирования из указанного, что потенциально быстрее чем создавать объект с дефолтовым конструктором и потом присваивать ему значение
Верно, но это не только потенциально быстрее, но и потенциально медленнее, поскольку первый элемент вставляемой пары копируется всегда, в то время как при использовании map::operator[] реализация STL может обойтись без этого копирования.
Здравствуйте, Bell, Вы писали:
B>По крайней мере некоторые распространенные реализации используют тот же самый insert + make_pair в реализации map::operator[]. А поскольку по условию дубликаты в файле отсутствуют, то логичнее сразу же использовать insert — элементы вставляются всегда, "холостых" вызовов make_pair нет.
И все же использование map::insert вместо map:operator[]заставляет реализацию STL лишний раз копировать ключ.
Здравствуйте, Bell, Вы писали:
B>Более того, к минусам варианта с insert можно добавить то, что make_pair принимает аргументы и возвращает результат по значению.
Кстати, не знаешь, аргументы-то почему по-значению?
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Bell, Вы писали:
B>>Более того, к минусам варианта с insert можно добавить то, что make_pair принимает аргументы и возвращает результат по значению.
I>Кстати, не знаешь, аргументы-то почему по-значению?
Возможно, чтобы избежать проблем с появлением "ссылки на ссылку"
Здравствуйте, Bell, Вы писали:
B>По крайней мере некоторые распространенные реализации используют тот же самый insert + make_pair в реализации map::operator[].
Видимо это было давно — иначе откуда я об этом помню?
В STLPort5 и в DinkumSTL для VC7.1 map::operator[] реализован без использования make_pair...
Здравствуйте, Bell, Вы писали:
B>Видимо это было давно — иначе откуда я об этом помню? B>В STLPort5 и в DinkumSTL для VC7.1 map::operator[] реализован без использования make_pair...
В VC9 тем не менее сначала конструируется map::value_type, затем при вставлении копируется в node, после чего сконструированное значение уничтожается. То есть избавились от make_pair, но избыточное копирование оставили.
mapped_type& operator[](const key_type& _Keyval)
{ // find element matching _Keyval or insert with default mapped
iterator _Where = this->lower_bound(_Keyval);
if (_Where == this->end()
|| this->comp(_Keyval, this->_Key(_Where._Mynode())))
_Where = this->insert(_Where,
value_type(_Keyval, mapped_type()));
return ((*_Where).second);
}
};
Здравствуйте, igna, Вы писали:
I>В VC9 тем не менее сначала конструируется map::value_type, затем при вставлении копируется в node, после чего сконструированное значение уничтожается. То есть избавились от make_pair, но избыточное копирование оставили.
I>
Здравствуйте, igna, Вы писали:
I>При завершении программы std::map записывается в файл, из которого этот же std::map заполняется при повторном запуске программы. Что вы используете для заполнения, map::insert или map::operator[]?
boost::serialization
Одним махом всю мапу сохраняет и загружает*. При бинарной сериализации работает быстро.
Здравствуйте, TimurSPB, Вы писали:
TSP>boost::serialization
Честно говоря мне не задачу нужно решить, просто попался на глаза Скотт-Мейерсовский "Совет 24. Тщательно выбирайте между map::operator[] и map::insert", который (совет) в общем случае неверен.
Здравствуйте, Alexander G, Вы писали:
AG>insert в цикле с результатом предыдущего insert в качестве хинта
Ответ правильный, вопрос неправильный. То есть задачу я сформулировал не так, как собственно хотел. А хотел я сравнить именно map::operator[] и map::insert как это делается у Скотта Мейерса в "Совет 24. Тщательно выбирайте между map::operator[] и map::insert". Ну ладно, как сформулировано — так сформулировано, и при этой формулировке я скорее всего вообще не использовал бы insert, а написал бы итератор читающий файл и инициализировал бы map парой итераторов.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Здравствуйте, igna, Вы писали:
I>>Здравствуйте, Bell, Вы писали:
B>>>Более того, к минусам варианта с insert можно добавить то, что make_pair принимает аргументы и возвращает результат по значению.
I>>Кстати, не знаешь, аргументы-то почему по-значению?
ЮЖ>
Library Defect Report #181
ЮЖ>Discussion:
ЮЖ>The claim has surfaced in Usenet that expressions such as
ЮЖ> make_pair("abc", 3)
ЮЖ>are illegal, notwithstanding their use in examples, because template instantiation tries to bind the first template parameter to const char (&)[4], which type is uncopyable.
ЮЖ>I doubt anyone intended that behavior...
ЮЖ>Proposed resolution:
ЮЖ>In 20.2 [utility], paragraph 1 change the following declaration of make_pair():
ЮЖ>template <class T1, class T2> pair<T1,T2> make_pair(const T1&, const T2&);
ЮЖ>to:
ЮЖ>template <class T1, class T2> pair<T1,T2> make_pair(T1, T2);
...
If P is instantiated as a reference type, then the argument x is copied from. Otherwise x is considered to be an rvalue as it is converted to value_type and inserted into the map. Specifically, in such cases CopyConstructible is not required of key_type or mapped_type unless the conversion from P specifically requires it
Здравствуйте, igna, Вы писали:
I>В VC9 тем не менее сначала конструируется map::value_type, затем при вставлении копируется в node, после чего сконструированное значение уничтожается. То есть избавились от make_pair, но избыточное копирование оставили.
Ну, если учесть, что избыточные копирования убираются оптимизатором компилятора...
C>А мы теперь с этим кривым и стандартным работаем...
А как предлагешь поступить с завершающим '\0' в asciiz стрках?
Как быть с другими типами, где 0й элемент может иметь иной смысл?
.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth