-
Notifications
You must be signed in to change notification settings - Fork 0
CPP 02. Ссылки. lvalue и rvalue ссылки. Передача параметров в функции по ссылке. Автоматическое выведение типа.
Ссылка (alias) – механизм передачи параметров в функцию и возврата из функции. По сути это ещё одно имя того же самого данного.
Ссылка - не тип данных!
Ссылка всегда инициализирована (не может указывать на null)
Пример:
int i;
int& ai = i;
ai = 5; //то же самое, что и i = 5;
Но такое использование ссылок - абсурд. Ссылки надо использовать для того, чтобы избавиться от указателей.
О возврате. Нельзя возвращать ссылку на локальную переменную. Возврат по ссылке нужен для формирования левого выражения = , чтобы присвоить переменной нужное значение.
Lvalue ссылки - это ссылки на существующие объекты, которые имеют имена. Они объявляются с помощью оператора "&". Пример объявления lvalue ссылки:
int a = 10;
int& b = a; // объявление lvalue ссылки на переменную a
Rvalue ссылки - это ссылки на временные объекты, которые не имеют имена. Они объявляются с помощью оператора "&&". Пример объявления rvalue ссылки:
int&& c = 20; // объявление rvalue ссылки на временный объект
Примеры из лекций:
#include <iostream>
void f(int) {}
int main()
{
int i = 0;
int& lref1 = i;
int& lref2(i);
int& lref3{ i };
int& lref4 = { i };
int& lv1 = i;// Ok!
int& lv2 = 2;// Error!(не lvalue)
int& lv3 = i + 1;// Error!(не lvalue)
const int& lv4 = i + 1;// Ok!(создается объект)
++lv1;// Ok!
int&& rv1 = i;// Error!(не rvalue)
int&& rv2 = 2;// Ok!
int&& rv3 = i + 1;// Ok!
const int&& rv4 = i + 1;// Ok!
++rv2;// Ok!
int&& rv5 = rv2;// Error!(не rvalue)
int& lv5 = rv2;// Ok!
int&& rv6 = (int)i;// Ok!( int(i) )
int&& rv7 = std::move(i);// Ok!
void(&reff)(int) = f;
reff(1);
}
Передача параметров в функции по ссылке позволяет изменять значения объектов внутри функции, не создавая копий объектов. Для передачи параметров по ссылке используются lvalue ссылки.
Пример:
void swap(int& x, int& y) {
int temp = x;
x = y;
y = temp;
}
int a = 10, b = 20;
swap(a, b);
Автоматическое выведение типа - это возможность компилятора определить тип переменной на основе значения, которое ей присваивается. Для автоматического выведения типа используется ключевое слово "auto".
Примеры из лекций:
# include <iostream>
int main()
{
int i = 0;
const int ci = 0;
int& lv = i;
const int& clv = ci;
int&& rv = i + 1;
// тип int
{
auto x1 = i;
auto x2 = ci;
auto x3 = lv;
auto x4 = clv;
auto x5 = rv;
auto x6 = i + 1;
}
// тип int&
{
auto& refx1 = i;
auto& refx3 = lv;
auto& refx5 = rv;
}
// тип const int&
{
auto& crefx2 = ci;
auto& crefx4 = clv;
}
// тип const int&
{
const auto& crefx1 = i;
const auto& crefx2 = ci;
const auto& crefx3 = lv;
const auto& crefx4 = clv;
const auto& crefx5 = rv;
const auto& crefx6 = i + 1;
}
// тип int&
{
auto&& refx1 = i;
auto&& refx3 = lv;
auto&& refx5 = rv;
}
// тип const int&
{
auto&& crefx2 = ci;
auto&& crefx4 = clv;
}
// тип int&&
{
auto&& refx6 = i + 1;
}
}