Что означает && возле типа и когда использовать?

Рейтинг: 0Ответов: 2Опубликовано: 07.06.2023

Я знаю, что есть указатели * и ссылки &. Первое для адресов, чтобы не копировать значения лишний раз, а второе то же самое, но без явного разыменования и взятия адреса. Но что такое двойная ссылка &&? Когда её надо использовать для объявления моих переменных?

Ответы

▲ 2

T && x = .. - это объявление ссылки на объект, у которого заканчивается время жизни или он вообще временный объект.

int f ( int x ) {
  return x + 1 ;
}

int && r = f ( 1 ) ;

Это объявление можно использовать для оптимизации, чтобы не было и мысли для создания копии возвращаемого объекта. И ссылка r будет ссылаться на временный возвращаемый объект функцией f. Этому временному объекту будет увеличена время жизни до конца видимости переменной r.


Нельзя создавать переменную данной ссылкой, если функция возвращает не объект, а && ссылку. Так как после завершения выполнения функции у этих временных объектов может заканчиваться срок жизни. И ваша новая ссылка будет уже неликвидная.

int && g ( int && x ) {
  return static_cast<int&&>(x) ;
}

int && r = g ( 1 ) ; // так нельзя

У временного объекта 1 заканчивается время жизни после завершения выполнения функции g и ссылка r будет уже указывать на удалённый временный объект.
В таких случаях нужно возвращать копию объекта, а не ссылку.

int g ( int && x ) {
  return static_cast < int && > ( x ) ;
}

int && r = g ( 1 ) ; // можно

Из-за непредсказуемого поведения времени жизни возвращаемого временного объекта, лучше всегда из функции возвращать только копию.

▲ 0

Это rvalue ссылка. В объявлении переменных надо использовать, когда то, чем инициализируете является rvalue ссылкой и при этом у вас нет move конструктора.

NonMovable&& a = get_rvalue_reference_to_NonMovable()

auto&& это forwarding ссылка. В объявлении переменных надо использовать, когда интересна константность или категория выражения, возвращаемая инициализатором. Обычно это надо в обобщённом коде для идеальной передачи возвращаемого значения. Например, в итерировании по вектору неизвестного типа можно использовать, чтобы работало и для вектора bool.