из пункта 8.5.3/2 C++ 11 стандарта на:
Ссылка не может быть изменена, чтобы ссылаться на другой объект после инициализации. Обратите внимание, что инициализация ссылки трактуется совсем иначе, чем присвоение ей. Прохождение аргумента (5.2.2) и Значение функции return (6.6.3) - это инициализации.
В основном это говорит о том, что возврат значения из функции эквивалентно выполнению инициализации. Таким образом, функция f3()
не компилируется по той же причине последней инициализации в фрагменте кода ниже не компилировать:
char c = 'a';
char* x = &c;
const char*& y = x; // ERROR!
Тип объекта, на который ссылается y
является const char*
, в то время как тип выражения мы пытаются инициализировать его (т. е. тип x
) - char*
. Это различных типов, и при привязке ссылки типы выражения инициализатора и объекта, на который ссылается инициализированная ссылка , должны быть идентичными (за исключением базовых и производных классов, которые здесь не задействованы), кроме верхний уровень cv квалификация.
Здесь const
квалификации в const char*
является не квалификацией верхнего уровня, так как он относится к остроконечному предмету, а не к самому указателю: в то время как остроконечные char
значение не может быть изменено через const char*
указатель, то сам указатель может быть переназначен.
В стандартных условиях, это означает, что типы const char*
и char*
не являются ссылки, связанные с:
Указанные типы «cv1 T1
» и «cv2 T2
», «cv1 T1
» является ссылки, связанные с к «cv2 T2
», если T1
является того же типа, что иT2
, или T1
является базовым классом T2
.«CV1 Т1» является справочника-совместимым с «cv2 T2
», если T1
является ссылка связанных сT2
и cv1
одно и то же резюме-квалификация, как, или больше резюме, чем-квалификация, cv2
. [...]
С другой стороны, функция f2()
компилирует, последовательно с тем, что инициализация в последней строке ниже законна:
char c = 'a';
char* x = &c;
char* const& y = x; // OK
Здесь, тип ссылочного объекта составляет char* const
, который (в отличие от const char*
) является ссылочным-совместимым с char*
в смысле, определяемом приведенным выше абзацем * (квалификация const
- квалификация в этом случае).
В частности, за 8.5.3/5:
Ссылка на тип «CV1 T1» инициализируется выражением типа «CV2 Т2» следующим образом:
- Если ссылки является ссылка Левой и выражение инициализатора
- является именующей (но не битовым поле), и «CV1 Т1» является ссылкой совместит с «CV2 Т2,» или
[...]
Пропущенная часть не имеет отношения к этому делу. Здесь char* const
и char*
являются эталонной совместимостью, а инициализация является законной (и f2()
компиляции). С другой стороны, const char*
и char*
: неСсылка, и инициализация незаконна (и f3()
не компилируется).
Что такое квалификация высшего уровня? Как вы охарактеризовали термин «верхний уровень» в этом контексте? – Belloc
@ user1042389: Я попробую пример: в 'int const' и' int * const', 'const' - это верхний уровень; в 'int const *' (который является таким же, как 'const int *'), 'const' не является верхним уровнем, потому что он применяется к указанному« int », а не к самому указателю. В общем, на C++ вы можете создавать сложные типы с помощью таких конструкций, как «указатель на», «ссылка на», «массив» и т. Д. Когда вы создаете тип таким образом (например, «ссылка на указатель на указатель« char »)) ваш тип имеет иерархическую структуру (цепочка, в нашем случае). Квалификатор верхнего уровня - это квалификатор, который применяется к верхнему узлу этой структуры –