С++: ссылка const, перед vs после спецификатора типа

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

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

и

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

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

Ответ 1

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

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

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

Ответ 2

Поведение

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

Как стиль

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

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

Что можно сказать о правиле синтаксического анализа справа налево?

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

Ответ 3

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

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

Ответ 5

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

Почему? Когда я изобрел "const", (первоначально называемый "только для чтения" и соответствующий "writeonly" ), я разрешил он должен идти до или после типа потому что я мог сделать это без неоднозначность.

Ответ 7

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

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

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

Последнее: даже если const type звучит более корректно на английском языке, запись type const позволяет более систематически понимать декларации "справа налево": int const & ref может быть прочитано имеет 'ref - это ссылка на константу INT". Или более сложный пример: int const * const & ref, ref - ссылка на константный указатель на константу int.

Заключение: в вашем вопросе оба эквивалентны.