C ++: константная ссылка, перед vs после спецификатора типа

145

В чем разница между аргументами в:

int foo1(const Fred &arg) {
...
}

и

int foo2(Fred const &arg) {
...
}

? Я не вижу этого случая в FAQ по Parashift.

eisbaw
источник
2
это вопрос стиля? "const Fred" звучит хорошо на английском, но "Fred const" выглядит лучше для меня.
LatinSuD
1
На соответствующую записку, есть какая - либо причина следует предпочесть Fred const &argболее Fred const& arg? Мне больше нравится последний, потому что там const&есть единица, означающая «constref», а имя argотделяется пробелом от всех спецификаторов типа.
Франк
4
@dehmann: Но int const& refне означает «const ref», а «ref to const».
Седрик Х.
1
Дубликат: stackoverflow.com/questions/2640446/…
Майкл Аарон Сафьян

Ответы:

112

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

Fred& constбудет означать, что сама ссылка является неизменной, что является избыточным ; при работе с константными указателями как Fred const*и Fred* constсправедливы , но разные.

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

Шон Фосетт
источник
Тогда какой смысл std::is_const<const T&>::valueбыть false?
бездна.7
@ abyss.7 это ссылка на const T; ссылка изменчива.
Шон Фосетт
125

Поведение

Там нет семантической разницы между const T&и T const&; язык относится к ним как к одному типу. (То же самое относится const T*и к T const*.)

Как вопрос стиля

Что касается того, что вы должны предпочесть стилистически, тем не менее, я не согласен с многими другими ответами и предпочитаю const T&const T*):

  • const T&это стиль, используемый в книге Страуструпа « Язык программирования C ++» .
  • const T& это стиль, используемый в самом стандарте C ++.
  • const T*это стиль, используемый в книге « Язык программирования Си» от K & R.
  • const T* это стиль, используемый в стандарте C.
  • Из-за вышеперечисленных факторов, я думаю const T&/ const T*инерция гораздо больше, чем T const&/ T const*. const T&/ const T*эмпирически кажется мне более распространенным, чем T const&/ T const*во всем коде C ++ и C, которые я видел. Я думаю, что следование общепринятым практикам более читабельно, чем догматическое соблюдение правил синтаксического анализа справа налево.
  • С T const*, кажется , легче теряются , *как T* const(особенно , если люди не так привыкли к нему). Напротив, const* Tэто не юридический синтаксис.

Как насчет правила синтаксического анализа справа налево?

Относительно всего аргумента синтаксического анализа справа налево, который люди, кажется, любят использовать: как я уже упоминал в комментарии к другому ответу, const T&читается также хорошо справа налево. Это ссылка на постоянную T. «Т» и «постоянный» каждый может работать как прилагательное или существительное. (Кроме того, чтение T const*справа налево может быть неоднозначными , поскольку она может быть неправильно интерпретирована как «указатель константа к Т» вместо того , чтобы как «указатель на постоянная Т») .

jamesdlin
источник
3
+1, согласился. При чтении кода легче определить const, если строка начинается с const. Правило справа налево действительно необходимо только при ручном разборе особенно типичных объявлений типов. Почему бы не оптимизировать для наиболее распространенного случая? Кроме того, IMHO, если вы пишете объявления типов, поэтому вам нужно вручную запустить FSM в своей голове, вы делаете это неправильно.
Андреас Магнуссон
2
-1. Независимо от того, насколько обоснованы ваши выводы и насколько я лично с ними согласен, они не отвечают на заданный вопрос напрямую. Это приводит к тому, что второй ответ на простой вопрос выглядит как не по теме бред о какой-то грязной подводной аппаратуре, без выводов, без прямого ответа - ничего. Вы получите мое одобрение, когда добавите простое ясное резюме, в котором говорится: « Нет, между двумя синтаксисами нет семантической разницы , но есть некоторые стилистические соображения, как изложено ниже ...». И только тогда все эти пули.
ulidtko
1
ИМО причина const T&читается лучше, в том, что: 1- Мы читаем код слева направо. И 2- При описании новой концепции мы начинаем с более общей концепции с более конкретной. Здесь constключевое слово является более общим, поскольку оно разделяет пространство переменных на две категории, тогда как спецификатор типа делит его на многие.
pooya13
«Указатель на» должен оставаться вместе. Так что нет никакой двусмысленности дляT const*
Декстер
13

Хотя они и одно и то же, для сохранения согласованности с правилом RIGHT-LEFT о разборе объявлений C и C ++ лучше написатьFred const &arg

Также обращайтесь к этому для более глубокого понимания объявлений, квалификаторов и объявлений.

Chubsdad
источник
1
Я предпочитаю суффикс, потому что он работает лучше с typedefрасширением. Пример: typedef int* pointer;, const pointer не является const int* , это int* const. Форма суффикса не неудобна.
Матье М.
4
ИМО const T&тоже хорошо читает справа налево; это ссылка на константу T. Tи constantкаждый может работать как прилагательное или существительное.
Джеймсдлин
7

И работа, и вот объяснение от человека, который написал это.
Процитирую его:

Зачем? Когда я изобрел «const» (изначально назывался «только для чтения» и имел соответствующее «только для чтения»), я позволил ему идти до или после типа, потому что я мог сделать это без двусмысленности.

По умолчанию
источник
3

Ссылки не работают так же, как указатели: для указателей у вас могут быть «const pointers» ( type * const p) и «указатель на const» ( const type * pили type const * p).

Но у вас нет этого для ссылок: ссылка всегда будет ссылаться на один и тот же объект; в этом смысле вы можете считать, что «ссылки» являются «константными ссылками» (так же, как вы можете иметь «константные указатели»).

Поэтому что-то вроде 'type & const ref' не является законным. Вы можете иметь только «ссылку на тип» ( type &ref) и «ссылку на тип константы» ( const type &refили type const &ref; оба точно эквивалентны).

И последнее: даже если const typeзвучит более корректно на английском языке, письмо type constпозволяет более систематически понимать объявления «справа налево»: int const & refможно прочитать с помощью «ref - ссылка на константу int». Или более сложный пример: int const * const & refref - ссылка на постоянный указатель на константу int.

Вывод: в твоем вопросе оба абсолютно эквивалентны.

Седрик Х.
источник