Как работает эта константная ссылка для std :: pair? - PullRequest
2 голосов
/ 11 марта 2019

Рассмотрим std::map класс в STL:

template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

Итераторы std::map возвращают объекты типа

std::pair<const key_type, T>

Важно отметить, что первый член пары - const. Это означает, что следующее ссылочное присвоение является недействительным .

std::pair<key_type, T>& reference = *map_iterator;        // Incorrect, key_type is not const

std::pair<const key_type, T>& reference = *map_iterator;  // Correct

Однако допустимо следующее выражение :

const std::pair<key_type, T>& reference = *map_iterator;  // Correct, const reference is okay

Таким образом, по некоторому механизму объекты типа std::pair<const key_type, T> могут ссылаться ссылкой типа const std::pair<key_type, T>. Это логически желательно (поскольку const ness std::pair подразумевает const ness обоих членов first и second, что совместимо с std::pair<const key_type, T>).

Однако мне интересно знать, какой механизм реализации C ++ делает эту совместимость возможной. Я уверен, что есть способы реализации std :: pair, где два указанных выше ссылочных типа не будут совместимы.

1 Ответ

6 голосов
/ 11 марта 2019

Когда вы делаете

const std::pair<key_type, T>& reference = *map_iterator;

*map_iterator возвращает std::pair<const key_type, T>&. Затем вы копируете инициализацию std::pair<key_type, T> и затем связываете reference с этой временной переменной. Поскольку у вас есть ссылка на const, это увеличит время жизни этого временного элемента до времени жизни ссылки, и теперь у вас есть элемент, который является копией элемента с карты. В основном вы сделали

std::pair<key_type, T> copy = *map_iterator; 

Приведенная выше последовательность преобразования работает, потому что вам разрешено до одного пользовательского преобразования при инициализации, и компилятор попытается сделать это, чтобы дать вам действительную инициализацию.

...