2012-01-10 4 views
1

У меня есть базовый запрос в картах C++,C++ карты добавляет новый элемент

map<char,string> mymap; 

    mymap['a']="an element"; 
    mymap['b']="another element"; 
    mymap['c']=mymap['b']; 

    cout << "mymap['a'] is " << mymap['a'] << endl; 
    cout << "mymap['b'] is " << mymap['b'] << endl; 
    cout << "mymap['c'] is " << mymap['c'] << endl; 
    cout << "mymap['d'] is " << mymap['d'] << endl; 

при попытке получить доступ к MyMap [ «d»], я получаю значение по умолчанию, так как оператор вставляет новый элемент в с этим ключом и инициализируется значением по умолчанию, хотя он доступен только для получения его значения. В следующий раз, когда я использую итератор, я мог видеть нулевое значение для ключа 'd'. Есть ли способ ограничить отображение карты значениями по умолчанию.

+0

Что вы * * ожидать произойдет, когда вы пишете 'MyMap [ 'd']'? –

+2

Если вы прочли этот код со страницы http://www.cplusplus.com/reference/stl/map/operator%5B%5D/, было бы вежливо упомянуть об этом.Тем более, что эта страница представляет и отвечает на ваш вопрос. " Обратите внимание, как последний доступ (к элементу 'd') вставляет новый элемент на карте с этим ключом и инициализируется значением по умолчанию (пустая строка), даже если к нему обращаются только для получения его значения. Карта функций-членов: : find не производит этого эффекта ». –

ответ

8

Вы должны использовать map.find вместо operator [], если вы не хотите устанавливать по умолчанию.

map::find

iterator find (const key_type& x); 
const_iterator find (const key_type& x) const; 

Поискового контейнер для элемента с й, как ключ и возвращает итератор к нему, если найдено, в противном случае она возвращает итератор к карте :: конца (элемент в конце прошлого контейнер)

1

Это ожидаемое и задокументированное поведение std::map. Чтобы проверить наличие какого-либо предмета, используйте find.

0
map<char, string>::iterator mIte = mymap.find('d'); 
if(mIte != mymap.end()) 
cout << "mymap['d'] is " << mIte->second << endl; 
else 
cout << "mymap['d'] is empty" << endl; 
1

Используйте функцию-член карты iterator find(const key_type& k) только для запроса. Оператор МАП [] имеет некоторый «специальный эффект»

data_type& operator[](const key_type& k) 

Возвращает ссылку на объект, который связан с определенным ключом. Если в карте еще нет такого объекта, оператор [] вставляет объект по умолчанию data_type(). [3]

Больше ссылки можно найти на http://www.sgi.com/tech/stl/Map.html

0

Не только это документально поведение, но с немного подумав, что это легко понять, почему. Для операции индекса есть только два разумных результата: либо верните действительную запись на карте, либо выбросите исключение. Если вы не выбрали исключение, единственным выбором является создание новой записи. Я не знаю, почему стандарт выбрал один за другим, но так оно и есть.

Microsoft предоставляет метод at, который генерирует вместо создания элемента, но это не соответствует стандарту или gcc.

Это легко создать функцию, которая использует find сделать то же самое:

template<typename Key, typename Value> 
Value& at(std::map<Key,Value> & the_map, const Key & the_key) 
{ 
    std::map<Key,Value>::iterator it = the_map.find(the_key); 
    if (it == the_map.end()) 
     throw std::out_of_range("map index invalid"); 
    return it->second; 
} 

template<typename Key, typename Value> 
const Value& at(const std::map<Key,Value> & the_map, const Key & the_key) 
{ 
    std::map<Key,Value>::const_iterator it = the_map.find(thekey); 
    if (it == the_map.end()) 
     throw std::out_of_range("map index invalid"); 
    return it->second; 
} 
+0

'map :: at' определен в C++ 11, который GCC поддерживает только в последних версиях, и если вы его попросите (с помощью' -std = C++ 0x' или '-std = C++ 11'). –

0

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

В C++ 11, mymap.at('d') будет выдавать out_of_range, а не вставлять значение по умолчанию.

В C++ 03, вы можете эмулировать его с find:

template <typename Key, typename Value, typename C, typename A> 
Value at(std::map<Key,Value,C,A> const & map, Key const & key) 
{ 
    typename std::map<Key,Value,C,A>::const_iterator found = map.find(key); 
    if (found == map.end()) { 
     throw std::out_of_range("at(map,key)"); 
    } 
    return found->second; 
}