Может ли std:: map:: iterator возвращать копию значения или самого значения?
Я пытаюсь создать карту внутри карты:
typedef map<float,mytype> inner_map;
typedef map<float,inner_map> outer_map;
Смогу ли я поместить что-то внутри внутренней карты, или iterator:: second возвращает копию?
stl_pair.h предлагает последнее:
74: _T2 second; ///< @c second is a copy of the second object
но моя тестовая программа отлично работает с таким кодом:
it = my_map.lower_bound(3.1415);
(*it).second.insert(inner_map::value_type(2.71828,"Hello world!");
Итак, где же правда? Это копия или нет?
Ответы
Ответ 1
Комментарий в stl_pair.h
вводит в заблуждение в этом конкретном случае.
Не будет копии, так как map::iterator
на самом деле ссылается на исходные данные внутри карты (value_type
, которая сама является pair
), а не копией. Таким образом, iterator::second
также относится к исходным данным.
Ответ 2
Я хочу добавить ответ на этот вопрос для людей, использующих итераторы С++ 11...
Следующий код:
std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (auto i : m)
{
std::cout << i.first << ": " << i.second << std::endl;
}
копирует ключ и значение, так как "auto" является значением по умолчанию, а не ссылкой на const (по крайней мере, как он ведет себя clang 3.1).
Кроме того, код:
std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (const std::pair<std::string,std:string>& i : m)
{
std::cout << i.first << ": " << i.second << std::endl;
}
также копирует ключ и значение, так как правильный код должен быть:
std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (const auto& i : m)
{
std::cout << i.first << ": " << i.second << std::endl;
}
или
std::map<std::string, std::string> m({{"a","b"},{"c","d"}});
for (const std::pair<const std::string,std:string>& i : m)
{
std::cout << i.first << ": " << i.second << std::endl;
}
Ответ 3
Карта value_type
- это пара, и поэтому она имеет элементы первой и второй. Как и во всех итераторах, итератор карты является псевдо-указателем, то есть указывает на данные в коллекции, а не на копии этих данных.
Почти наверняка внутренне содержать указатели, а не ссылки, из-за того, что итераторы могут быть повторно назначены (для этого вы их используете), и вы не можете переназначить ссылки для ссылки на другие объекты.
Даже если у вас есть const_iterator, а тип под ним - POD, он должен иметь указатель на него, если кто-то это сделает:
map< int, int > m;
m.insert( make_pair( 1, 2 );
map<int,int>::const_iterator citer = m.begin();
map<int,int>::iterator iter = m.begin();
iter->second = 3;
std::cout << citer->second << '\n'; // should always print 3
Поведение должно быть определено и должно выводиться 3, что не произойдет, если const_iterator решил "оптимизировать" после него const и только int...
Ответ 4
Итераторы, при разыменовании, дают ссылку.