В C++11 была введена новая особенность языка - "универсальные ссылки" или "ссылки на rvalue-ссылки", которая позволяет передавать аргументы функции без потери эффективности и с поддержкой перемещения (move semantics).
Универсальная ссылка обозначается с помощью двойного амперсанда (&&) и может привязываться к обоим lvalue и rvalue. Когда универсальная ссылка связывается с rvalue, она позволяет использовать move semantics, а при связывании с lvalue - приведение lvalue к rvalue.
Правильно написать функцию, принимающую универсальную ссылку, можно следующим образом:
template <typename T> void foo(T&& arg) { // Внутри функции аргумент "arg" может использоваться как lvalue, // так и rvalue в зависимости от объекта, переданного при вызове функции. // Примеры использования универсальной ссылки: // 1. Копирование/перемещение аргумента "arg" T copy(std::forward<T>(arg)); // 2. Обработка аргумента "arg" process(std::forward<T>(arg)); // 3. Приведение аргумента "arg" к rvalue rvalue_func(std::move(arg)); }
В приведенном примере шаблонная функция foo
принимает универсальную ссылку arg
типа T&&
. T
- это тип аргумента, который будет выведен компилятором при вызове функции. Внутри функции можно использовать arg
и передавать его другим функциям, применяя std::forward
для сохранения обратной совместимости со значением lvalue или rvalue.
Важно отметить, что при передаче lvalue-аргумента (T&
), T
будет выведен как T&
, а при передаче rvalue-аргумента (T&&
), T
будет выведен как T
без ссылки. Это позволяет использовать механизм move semantics или приведение lvalue к rvalue внутри функции, что может быть полезно для оптимизации и обработки временных объектов.