В объявлении, T D где D есть одна из форм
& attribute-specifier-seqopt D1 && attribute-specifier-seqopt D1
и тип идентификатора в объявлении T D1 - «derived-declarator-type-list T», тогда тип идентификатора D - «derived-declarator-type-list ссылка на T». Необязательный параметр attribute-specifier-seqотносится к ссылочному типу. Ссылки с квалификатором cv имеют неправильный формат, за исключением случаев, когда cv-квалификаторы вводятся с использованием символа typedef-name([dcl.typedef], [temp.param]) или decltype-specifier, в этом случае, cv-квалификаторы игнорируются. [ Example:
typedef int& A;
const A aref = 3; // ill-formed; lvalue reference to non-const initialized with rvalue
Типом aref является «ссылка lvalue на int», а не «ссылка lvalue на const int». ] [ Ссылку можно рассматривать как имя объекта. ] Объявление, указывающее тип «ссылка на », имеет неправильный формат. — end example Note: — end note cv void
Ссылочный тип, объявленный с использованием & , называется lvalue reference, а ссылочный тип, объявленный с использованием && , называется rvalue reference. Ссылки Lvalue и ссылки rvalue - это разные типы. Если явно не указано иное, они семантически эквивалентны и обычно называются ссылками.
void f(double& a) { a += 3.14; }
// ...
double d = 0;
f(d);
объявляется a ссылочным параметром, f поэтому вызов f(d) будет добавлен 3.14 к d.
int v[20]; // ... int& g(int i) { return v[i]; } // ... g(3) = 7;
объявляет функцию g() для возврата ссылки на целое число, поэтому она g(3)=7 будет назначена 7 четвертому элементу массива v. Другой пример:
struct link {
link* next;
};
link* first;
void h(link*& p) { // p is a reference to pointer
p->next = first;
first = p;
p = 0;
}
void k() {
link* q = new link;
h(q);
}
объявляет p ссылку на указатель, link поэтому h(q) оставит q нулевое значение. См. Также [dcl.init.ref]. ] — end example
Не должно быть ссылок на ссылки, массивов ссылок и указателей на ссылки. Объявление ссылки должно содержать initializer ([dcl.init.ref]), за исключением случаев, когда объявление содержит явный extern спецификатор ([dcl.stc]), является class member объявлением в определении класса или является объявлением параметра или возвращаемого типа ([dcl.fct]); см [basic.def]. Ссылка должна быть инициализирована для ссылки на действительный объект или функцию. [ В частности, пустая ссылка не может существовать в четко определенной программе, потому что единственный способ создать такую ссылку - это привязать ее к «объекту», полученному косвенным путем через нулевой указатель, что вызывает неопределенное поведение. Как описано в , ссылку нельзя напрямую привязать к битовому полю. ] Note: [class.bit] — end note
Если typedef-name([dcl.typedef], [temp.param]) или a decltype-specifierобозначает тип, TR который является ссылкой на тип T, попытка создать тип «ссылка lvalue на cv TR» создает тип «ссылка lvalue на T», в то время как попытка создать тип «ссылка rvalue на cv TR» создает тип TR. [ Note: Это правило известно как сворачивание ссылок. ] [ — end note Example:
int i; typedef int& LRI; typedef int&& RRI; LRI& r1 = i; // r1 has the type int& const LRI& r2 = i; // r2 has the type int& const LRI&& r3 = i; // r3 has the type int& RRI& r4 = i; // r4 has the type int& RRI&& r5 = 5; // r5 has the type int&& decltype(r2)& r6 = i; // r6 has the type int& decltype(r2)&& r7 = i; // r7 has the type int&
— end example ]
[ Note: Формирование ссылки на тип функции неверно, если тип функции имеет cv-qualifiers или ref-qualifier; см [dcl.fct]. ] — end note