В чем разница между двумя следующими строками?
map<int, float> map_data;
map<const int, float> map_data;
В чем разница между двумя следующими строками?
map<int, float> map_data;
map<const int, float> map_data;
int
и const int
— это два разных типа.
std::map<int, float>
и std::map<const int, float>
также являются разными типами.
Разница между std::map<const int, float>
и std::map<int, float>
в какой-то степени аналогична разнице, скажем, между std::map<int, float>
и std::map<std::string, float>
; для каждого вы получаете новый тип карты.
В случае, отличном от const
, тип внутреннего ключа является по-прежнему отличным от const
int
:
std::map<const int, float>::key_type => const int
std::map<int, float>::key_type => int
Однако ключи карты семантически неизменяемы, и все операции карты, которые разрешают прямой доступ к ключам (например, разыменование итераторов, что дает value_type
), const
исправляют key_type
:
std::map<const int, float>::value_type => std::pair<const int, float>
std::map<int, float>::value_type => std::pair<const int, float>
Таким образом, разница может быть практически незаметной для вас во всех смыслах, если ваша реализация позволяет это.
Однако это не всегда так: стандарт официально требует, чтобы ваш тип ключа был копируемым и перемещаемым, а некоторые реализации повторно используют узлы карты; в этих реализациях попытка использовать ключ const
просто не сработает.
So the difference is largely invisible to you in every way that matters.
-- если вы не используете stdlib, который копирует/перемещает ключи (например, libc++), в этом случае версия const просто ломается. См. lists.cs.uiuc.edu/pipermail/cfe. -dev/2011-July/015926.html для соответствующего обсуждения.
- person mitchnull; 13.10.2014
const
, которая у меня была с картами. В C++14 появились прозрачные компараторы, которые немного усложняют работу, чтобы мы оставались четкими: )
- person vsoftco; 24.11.2016
const
нормально, они вам не понадобятся.
- person Lightness Races in Orbit; 01.05.2017
ключ уже имеет значение const
, поэтому в данном случае писать const
излишне. После ввода элемента его key
нельзя изменить.
Как упоминалось в комментариях, между двумя строками есть разница. Например, если вы пишете функцию, которая принимает map<const int, int>
, вы не можете передать ей map<int, int>
, так как они разные типы.
Но обратите внимание, что, хотя они и относятся к разным типам, они ведут себя одинаково, поскольку ключ на карте в любом случае является const
...
Итак, в заключение. Единственная разница в том, что это два разных типа, вам не нужно заботиться ни о чем другом.
std::map
предоставляет тип ключа как const
, но это не означает, что два экземпляра шаблона совпадают, как может подразумевать этот ответ. std::map<const int, float>
и std::map<int, float>
относятся к разным типам.
- person jrok; 14.07.2013
key_type
на самом деле все еще int
в первом случае.
- person Lightness Races in Orbit; 14.07.2013
const
(т.е. geordi << TYPE<std::map<int, float>::key_type>; # int
). Однако семантически он неизменен, и все операции, которые напрямую обращаются к ключам (например, разыменование итератора), дают вам const
версию значения ключа (т. е. geordi << TYPE<std::map<int, float>::value_type>; # std::pair<int const, float>
).
- person Lightness Races in Orbit; 14.07.2013
Отличие в том, что второй вариант установит тип ключа для карты как const int
. С точки зрения «модифицируемости» это избыточно, так как карта уже хранит свои ключи как const
объекты.
Однако это также может привести к неожиданным и неочевидным различиям в поведении этих двух карт. В C++ специализация шаблона, написанная для типа T
, отличается от специализации, написанной для типа const T
. Это означает, что две вышеупомянутые версии карты могут в конечном итоге использовать разные специализации различных «спутниковых» шаблонов, которые зависят от типа ключа. Одним из примеров является ключевой предикат компаратора. Первый будет использовать std::less<int>
, а второй — std::less<const int>
. Используя эту разницу, вы можете легко заставить эти карты сортировать элементы в другом порядке.
Подобные проблемы более очевидны с новыми контейнерами C++11, такими как std::unordered_map
. std::unordered_map<const int, int>
даже не будет компилироваться, так как попытается использовать std::hash<const int>
специализацию для хеширования ключей. Такой специализации нет в стандартной библиотеке.
const
нельзя изменить после установки. И да, согласно документам и другим ответам, вы должны помнить, что key
уже const
.
Ссылка: http://www.cplusplus.com/reference/map/map/ Ссылка: http://en.cppreference.com/w/cpp/container/map а>
Хотя поведение вашего приложения обычно будет таким же, оно имеет значение для некоторых компиляторов, которые вы можете использовать. Более конкретный пример того, что привело меня на эту страницу в первую очередь:
Явное указание карты как map<const key, value>
успешно строится с помощью инструментария gnu;
Однако это приводит к сбою сборки Studio12 Solaris x86.
map<key, value>
успешно строится на обоих. Поведение приложения не изменилось.
std::map::insert
имеет несколько объявлений.
- person blgt; 07.10.2013
Постоянные ключи могут быть полезны, если ключи являются указателями. Использование константных ключей не позволит вам изменить указанный объект при доступе к ключам, учтите это:
#include <map>
#include <string>
int glob = 10;
int main() {
std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
std::map<int*, std::string> keyMap { { &glob, "bar" } };
for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR
return 0;
}
key_type
равно const int*
, сам указатель не является константным, но указанный int
является константным.
- person lrineau; 02.04.2014
const относится к константе, которая после определения не может быть изменена, а затем... неконстантный ключ подвергается изменению... или даже не может быть изменен, просто в константе гарантируется "отсутствие изменений" (после определения) , а «изменение» может происходить или не происходить в неконстантных вещах.