У чому різниця між ключем const та non const?


Відповіді:


65
  • 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) виконує constify 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ключ просто не буде працювати.


1
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 для відповідного обговорення.
mitchnull

@mitchnull Так, гарне місце. ( до речі !)
Гонки легкості на орбіті

@LightnessRacesinOrbit "стандарт офіційно вимагає, щоб ваш тип ключа був копіюваним і переміщуваним". Щодо мобільності, я не можу знайти, що на моїй стандартній копії C ++ ви можете надати посилання або номер розділу?
Берен

Це відмінна відповідь, нарешті, вона прояснила цілісність, яку constя мав із картами. C ++ 14 представив прозорі компаратори, які додають трохи складності лише для того, щоб тримати нас чітко :)
vsoftco

А, дякую, що підтвердили, що ключі заборонені для const. Я хотів, щоб мої ключі були незмінними, і це збило мене з розуму -_-
Ноель Відмер

36

Ключ вже const, так що надмірно писати constв цьому випадку. Після введення елемента його keyне можна змінити.


Редагувати :

Як зазначалось у коментарях, між цими двома рядками є різниця. Наприклад, якщо ви пишете функцію, яка приймає map<const int, int>, ви не можете перейти до неї, map<int, int>оскільки це різні типи .

Але зауважте, що, хоча вони бувають різних типів, вони поводяться однаково, оскільки ключ на карті все constодно ...

Отже, на закінчення .. Єдина відмінність полягає в тому, що це два різні типи, ви не повинні дбати ні про що інше.


18
Це (не повністю) правильно. Інтерфейс std::mapвиставляє тип ключа як const, але це не означає, що обидва екземпляри шаблону однакові, що може означати ця відповідь. std::map<const int, float>і std::map<int, float>бувають різних типів .
jrok

1
@jrok є правильним, тоді як ця відповідь - ні. key_typeФактично ще intв першому випадку.
Гонки легкості на орбіті

6
@ johnmac2332: Нехай це буде урок, який швидко! = ідеально, і голоси! = правильно.
Гонки легкості на орбіті

1
@ johnmac2332 Швидкі та швидкі відповіді слід високо оцінити. Це одна з якісних програм Stackoverflow, краща за інші мережі. OP може подати подальший запит у розділі коментарів. якщо він скаже подяку, значить, мабуть, він отримав відповідь.
Grijesh Chauhan

2
Ніхто не ідеальний, ми всі робимо помилки і вчимося один у одного. Ми тут, щоб навчитися та допомогти :)
Марун

8

Різниця полягає в тому, що другий варіант встановить тип ключа для карти як 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>спеціалізацію для хешування ключів. Така спеціалізація не існує у стандартній бібліотеці.


3

constне може бути змінено після встановлення. І так, згідно з документами та іншими відповідями, ви повинні пам’ятати, що keyце constвже є .

Посилання: http://www.cplusplus.com/reference/map/map/ Посилання: http://en.cppreference.com/w/cpp/container/map


1
Вибачте, що я повинен був написати - не можу. Моди змінили - Дякую
Shumail

2

Хоча поведінка вашої програми, як правило, однакова, це впливає на деякі компілятори, якими ви можете скористатися. Більш конкретний приклад того, що спочатку привело мене до цієї сторінки:

Явно вказавши карту як map<const key, value> успішно будується за допомогою набору інструментів gnu;

Однак він аварійно завершує збірку Studio12 Solaris x86.


map<key, value>успішно будується на обох. Поведінка програми незмінна.


"Аварії" яким чином?
Гонки легкості на орбіті

@LightnessRacesinOrbit Він скаржився на std::map::insertнаявність кількох декларацій.
blgt

Так, як я вже говорив вище: це має значення для компілятора.
blgt

Зазвичай, коли ми говоримо "аварійне завершення роботи", ми маємо на увазі несподіване та неввічливе завершення процесу. Аварії компілятора трапляються рідко, але трапляються (особливо з новими мовними функціями) і мають дуже серйозний характер (у міру результатів збірки).
Гонки легкості на орбіті

Це падає мою збірку , а не додаток . Чи я зловживаю термінологією?
blgt

0

Клавіші 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;
}

1
Коли key_typeє const int*, вказівник сам не const, а загострений intconst.
lrineau

-1

const відноситься до константи, яку, визначивши, неможливо змінити тоді ... ключ non const піддається зміні ... або навіть не може змінитись, просто в const гарантується "відсутність змін" (коли вона визначена) , а "зміна" може відбуватися, а може і не відбуватися у неконстантних матеріалах.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.