У чому різниця між наступними двома рядками?
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
ify 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 просто ламається. Див. List.cs.uiuc.edu/pipermail/cfe-dev/2011-July/015926.html для відповідного обговорення.
const
я мав із картами. C ++ 14 представив прозорі компаратори, які додають трохи складності лише для того, щоб тримати нас чітко :)
Ключ вже const
, так що надмірно писати const
в цьому випадку. Після введення елемента його key
не можна змінити.
Як зазначалось у коментарях, між цими двома рядками є різниця. Наприклад, якщо ви пишете функцію, яка приймає map<const int, int>
, ви не можете перейти до неї, map<int, int>
оскільки це різні типи .
Але зауважте, що, хоча вони бувають різних типів, вони поводяться однаково, оскільки ключ на карті все const
одно ...
Отже, на закінчення .. Єдина відмінність полягає в тому, що це два різні типи, ви не повинні дбати ні про що інше.
std::map
виставляє тип ключа як const
, але це не означає, що обидва екземпляри шаблону однакові, що може означати ця відповідь. std::map<const int, float>
і std::map<int, float>
бувають різних типів .
key_type
Фактично ще int
в першому випадку.
Різниця полягає в тому, що другий варіант встановить тип ключа для карти як 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
наявність кількох декларацій.
Клавіші Const можуть бути корисними, якщо вони є покажчиками. Використання const-ключів не дозволить вам змінити загострений об’єкт під час доступу до ключів, враховуйте це:
#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*
, вказівник сам не const, а загострений int
const.
const відноситься до константи, яку, визначивши, неможливо змінити тоді ... ключ non const піддається зміні ... або навіть не може змінитись, просто в const гарантується "відсутність змін" (коли вона визначена) , а "зміна" може відбуватися, а може і не відбуватися у неконстантних матеріалах.