Точное соответствие между ссылками r-значения и указателями? - PullRequest
1 голос
/ 20 апреля 2020

Это общий вопрос о симметрии между указателем и ссылочными типами в языке C ++.

Является ли эта таблица соответствия значимой в C ++ (C ++ 11 и далее)?

| Reference | Pointer  |
|-----------|----------------|
| T&        | T* const       |
| T const&  | T const* const |
| T&&       | ???*           |

и, если таковые имеются, что будет соответствовать ???*?. (отсутствуют какие-либо дополнительные строки?)

(T&& для конкретного типа T, не выводимый тип. См. Ответ @ComicSansMS для завершающего const.)

Я думаю, это будет соответствовать чему-то вроде std::move_iterator<T*>, но это не встроенная языковая функция, и кажется, что она создает кучу других проблем (как это делает std::reference_wrapper).

В языке отсутствует какой-либо указатель r-значения, чтобы быть более симметричным c? Или лучше сказать что-то, что генерирует r-значения на объекте привязки (например, перемещенный объект - или даже копию).

Я знаю, что ссылки на r-значения соответствуют вещи, которая "не имеет имени" Однако, это не кажется ограничительным, если это то же самое получается только для операции почтения *.


ПРИМЕЧАНИЕ 1:

Я вижу std::move_iterator<It>::operator->() устарело в C ++ 20. Что я не уверен, что это значит, возможно, это означает, что это может быть реализовано, опционально, иногда. Этот вопрос относится к этому устареванию, потому что в принципе std::move_iterator<It>::operator->() может вернуть ???* вместо pointer. (Или верните move_iterator<pointer>, хотя это сгенерирует бесконечный регресс из ->() операторов ... если только не существует истинного указателя для завершения r-значений.)


ПРИМЕЧАНИЕ 2: Кандидат я могу представить, что отсутствует пропущенная строка:

| void& (not a thing)  | void*     |

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

Ответы [ 2 ]

2 голосов
/ 20 апреля 2020

Нет "симметрии между указателем и ссылочными типами". Или, по крайней мере, он не предназначен для этого. Вы можете интерпретировать язык так, как вам нравится, но любая симметрия, которую вы видите, является случайной.

В большинстве случаев ссылки на lvalue и rvalue работают одинаково. Принципиальные различия заключаются в том, что вы можете различать guish между ними по типу (и, следовательно, можете перегружать функции или влиять на создание экземпляров шаблонов на их основе), и у них разные правила для объектов, которые они связывают, особенно при разрешении перегрузки. Цель этого различия состоит в том, чтобы система типов более точно передавала категорию значений исходного объекта, чтобы пользователь мог больше узнать о том, что разумно делать с указанным объектом.

Указатели не нужно сделать это, чтобы им не нужно было проводить это различие.

0 голосов
/ 20 апреля 2020

Является ли эта таблица соответствия значимой в C ++ (C ++ 11 и более поздних версиях)?

Может быть полезной мысленной моделью думать о ссылках как о синтаксически ином способе достижения семантика указателя. Важнейшая вещь, отсутствующая в вашей таблице, заключается в том, что эквивалентом ссылки является не указатель, а константный указатель:

| Reference | Pointer        |
|-----------|----------------|
| T&        | T* const       |
| T const&  | T const* const |

Обратите внимание, что это очень грубое приближение к истине, которая быстро разрушается. Все предостережения от @ Николя Боласа применимы здесь. Кроме того, T const& будет привязываться к временным файлам, в то время как T const* const очень не будет.

Теперь о пропущенном ряду для T&&. Ментальная модель для T&& здесь является ссылкой, из которой вам всегда разрешено двигаться. В теле функции параметр T&& для этой функции может обрабатываться точно так же, как если бы это был параметр T&, причем особая семантика включается только тогда, когда речь идет о перемещении. Для вызывающей стороны указанной функции, с другой стороны, T&& отличается от любого из известных типов ссылок или указателей тем, что он не только будет связываться с неназванными временными файлами (как это делает T const&), но на самом деле он будет только привязывайся к временным и ничему другому. Возможно, вы сможете сами понять, почему эквивалентная концепция указателя, хотя и мыслимая, не была бы очень полезным дополнением к языку.

Относительно вашей заметки 1: Устаревшее означает, что вещь помечена для удаления из стандарта. Хотя реализации пока будут поддерживать его, это только для обратной совместимости, и новый код должен избегать использования устаревших функций. Причиной того, что эта функциональность в move_iterator больше не должна использоваться, является именно отсутствие концепции указателя, который является безопасным для использования в языке.

Относительно вашей заметки 2: По историческим причинам еще одно важное различие между указателями и ссылками заключается в том, что типы указателей в некоторой степени взаимозаменяемы. То есть указатель T* может быть приведен к U*, даже если T и U не связаны между собой типами. Такое поведение многими считается крайне опасным наследием C и считается в значительной степени нежелательным. Ссылки не позволяют такие преобразования в любом случае. Это должно дать вам подсказку о том, почему void& не является допустимым типом данных в языке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...