2009-02-03 2 views
43

У меня есть std::map вроде этого:Карты STL инициализируют примитивные типы на вставке?

map<wstring,int> Scores; 

Он хранит имена игроков и оценки. Когда кто-то получает счет, я бы просто сделать:

Scores[wstrPlayerName]++; 

Когда нет ни одного элемента в карте с ключом wstrPlayerName будет создать, но это инициализировать до нуля или нулевой до приращения или он остается неопределенным ?

Должен ли я проверить, существует ли элемент каждый раз перед приращением?

ответ

61

оператор [] выглядит следующим образом:

Value& map<Key, Value>::operator[](const Key& key); 

Если вы называете это с ключом, что пока не в карте, по умолчанию-построить новый экземпляр Value, положить его в карту под ключ вы прошли и вернете ссылку на него. В этом случае, у вас есть:

map<wstring,int> Scores; 
Scores[wstrPlayerName]++; 

Значение здесь INT и Интс является по умолчанию, возведенные как 0, так как если вы инициализируетесь их Int(). Другие примитивные типы инициализируются аналогично (например , двойных(), длинные(), BOOL() и т.д.).

В конце ваш код помещает новую пару (wstrPlayerName, 0) в карту, а затем возвращает ссылку на int, которую вы затем увеличиваете. Таким образом, нет необходимости проверять, существует ли элемент, если вы хотите, чтобы что-то начиналось с 0.

11

По умолчанию будет создан новый экземпляр value. Для целых чисел построение по умолчанию равно 0, поэтому это работает по назначению.

+1

Для целых чисел, по умолчанию * конструкция * на самом деле не вещь. По умолчанию * инициализация * оставляет их неинициализированными, если они не являются статическими. Maps * value * - инициализировать элементы, поэтому в случае целых чисел вы получаете нулевую инициализацию. – juanchopanza

5

Не следует проверять, существует ли элемент, прежде чем увеличивать его. Оператор [] делает именно то, что вам нужно, чтобы делать, как говорили другие.

Но что, если построенное по умолчанию значение не будет работать для вас? В вашем случае лучший способ найти, существует ли элемент, - это попытаться его вставить. Функция члена insert для std::map возвращает std::pair<iterator, bool>. Будет ли вставка успешной или неудачной, первый элемент пары укажет на желаемый объект (либо ваш новый, либо тот, который уже присутствовал). Затем вы можете изменить его значение по своему усмотрению.

4

Спасибо за помощь.

Так СТД :: карты задавать их значение примитивного типа 0.

Я просто подумал, потому что я думал, что примитив типа вещи всегда неопределенные при создании.

Если я пишу что-то вроде:

int i; 
i++; 

компилятор предупреждает меня, что я не определен, и, когда я запускаю программу, она, как правило, не равна нулю.

+7

На самом деле это особенность языка C++. Если вы явно вызываете конструктор int (int i = int()), как std :: map, он будет инициализирован равным нулю. Голый int i все равно будет неинициализирован. –

+2

действительно, потому что «int i;» не будет по умолчанию инициализировать int (в отличие от типов классов). он оставит его значение неопределенным. same: struct a {int i; }; << значение i не определено. struct a {a(): i() {} int i; }; << i значение 0 –

+0

Повесьте. Если у вас есть структура A {int i; }; и затем вы создаете объект типа A, например. A myA = A(); то myA.i будет 0, потому что вызов/использование A() инициализирует весь myA равным 0, поэтому он будет равен 0. См. http://en.cppreference.com/w/cpp/language/zero_initialization – Will

1

Проверить правила для инициализации.

См. Раздел 4.9.5 Инициализация книги STD Prog Lang или C++. В зависимости от того, является ли ваша переменная локальной, может возникнуть статическая, пользовательская или инициализация по умолчанию const.

В вашем случае int называется POD (обычный старый тип данных). Любая автоматическая (созданная в переменной кучи/локальная переменная) переменная POD не инициализируется по умолчанию. Следовательно, для вас «i» выше не будет иметь нулевое значение.

Всегда делайте привычку инициализировать POD, когда он определен в куче. Вы можете даже использовать int() для инициализации значения.

+3

То, что вы сказали о POD, правильно, но OP спрашивает об инициализации, выполняемой std :: map. Ваш ответ не применяется и может смущать читателей, поскольку он, по-видимому, противоречит другим ответам. – MatthewD

+0

Хорошо, ваш ответ на самом деле отвечает на ответ Кальмариуса, который сейчас ** ниже ** (а не ** выше **), поскольку я читаю его сейчас. Это действительно должен быть комментарий там, а не отдельный ответ. – MatthewD

+0

Как ответ на поставленный вопрос, это совершенно неправильно. – juanchopanza

Смежные вопросы