Возвращает ли std :: map :: iterator копию значения или само значение? - PullRequest
24 голосов
/ 21 марта 2011

Я пытаюсь создать карту внутри карты:

typedef map<float,mytype> inner_map;
typedef map<float,inner_map> outer_map;

Смогу ли я поместить что-то внутрь внутренней карты, или итератор :: 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!");

Так где же правда? Это копия или нет?

Ответы [ 4 ]

25 голосов
/ 18 декабря 2012

Я хочу добавить дополнительный ответ на этот вопрос для людей, использующих итераторы C ++ 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;
}
24 голосов
/ 21 марта 2011

Комментарий в stl_pair.h вводит в заблуждение в данном конкретном случае.

Будет нет копии, поскольку map::iterator фактически ссылается на исходные данные внутри карты (value_type, которая сама по себе pair), это не копия.Таким образом, iterator::second также относится к исходным данным.

4 голосов
/ 21 марта 2011

Карта 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 решит "оптимизировать" после того, как все это константно и только int ...

0 голосов
/ 21 марта 2011

Итераторы, при разыменовании дают вам ссылку .

...