Почему ссылка .секунда на const std::pair& возвращает копию второго значения, а не константную ссылку?

Я пытаюсь получить указатели 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, что кажется действительно глупым?

Должно быть pair<const int, double>.

Jarod42 27.08.2024 12:03

В данном случае я бы, наверное, предпочёл const auto& cPair или даже const auto& [key, value].

Mestkon 27.08.2024 12:04

кстати, использовать итераторы не так уж и глупо, мы делали это пару десятилетий. А с итераторами вы также можете использовать autofor (auto it = intMap.begin(); ....

463035818_is_not_an_ai 27.08.2024 13:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Почему я не могу (или как я могу) заставить .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.

Caleth 27.08.2024 12:24

Ключи в 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;»?.

Другие вопросы по теме