Я пытаюсь получить указатели const на каждое значение в std::map. Я попробовал const pair<...>& с атрибутом .second, но получил неправильные указатели. Однако const_ierator подходит.
Кусок простого игрушечного кода:
const map<int, double> intMap = {{1, 3.3}, {4, 5.7}, {2, 8.314}};
const double* cPtr;
for (const pair<int, double>& cPair: intMap)
{
cPtr = &(cPair.second);
cout << cPtr << endl;
}
cout << endl;
for (
map<int, double>::const_iterator mapIter = intMap.begin();
mapIter != intMap.end();
mapIter ++
)
cout << &(mapIter -> second) << endl;
Что возвращает:
0x7ffc553c8210 # wrong pointers
0x7ffc553c8210
0x7ffc553c8210
0xb3ced8 # which I want
0xb3cf58
0xb3cf18
Мои вопросы:
.second из const pair<>& возвращать ссылку, а не копию?const pair<>&, есть ли более удобный способ получить ссылки на значения вместо использования const_iterator, что кажется действительно глупым?В данном случае я бы, наверное, предпочёл const auto& cPair или даже const auto& [key, value].
кстати, использовать итераторы не так уж и глупо, мы делали это пару десятилетий. А с итераторами вы также можете использовать autofor (auto it = intMap.begin(); ....





Почему я не могу (или как я могу) заставить
.secondизconst pair<>&возвращать ссылку, а не копию?
Копирование происходит не с .second, а с несоответствующим типом std::pair.
Вызов итератора карты (const) возвращает /*const*/std::pair<const Key, Value>& (обратите внимание на лишний const).
Когда ты это делаешь
for (const pair<int, double>& cPair: intMap)
У вас есть временный pair<int, double>, созданный из pair<const int, double> (поэтому вы видите тот же адрес).
Если я не могу получить то, что хочу, с помощью
const pair<>&, есть ли более удобный способ получить ссылки на значения, чем использовать const_iterator, что кажется очень глупым?
Вы можете с правильным типом:
for (const std::pair<const int, double>& cPair : intMap)
или с auto менее явным текстом, но без опечаток:
for (const auto& cPair : intMap)
или в C++17 с привязкой структуры
for (const auto& [i, d] : intMap)
Вместо const auto& cPair вы также можете использовать decltype(intMap)::const_reference cPair.
Ключи в std::map — это const, поэтому вам следует изменить:
for (const pair<int, double> & cPair: intMap)
К:
//--------------vvvvv------------------------------
for (const pair<const int, double> & cPair: intMap)
Чтобы получить желаемый результат (ваш текущий код создает временный объект, на который вы ссылаетесь в цикле).
Вы можете избежать этой проблемы, явно указав тип ключа как const, используя auto:
//---------vvvv------------------
for (const auto & cPair : intMap)
Примечание:
Лучше избегать using namespace std; - см. В чем проблема с «использованием пространства имен std;»?.
Должно быть
pair<const int, double>.