左值引用
- 引用必须在声明的时候初始化
-
int x; int &rx = x; //z注意这里的&位置是和int相连 //或 int x, &rx = x;
-
- 引用一旦初始化,引用名字就不能再指定给其它变量
- 通过引用所做的读写操作实际上是作用于原变量上
-
int a{0}, b{1}; // 即int a=0; int &r{a}; // 引用变量 r 在声明的同时就要初始化,r是a的别名 r = 42; // 相当于 a = 42 r = b; // 相当于 a = b; 执行后 a 的值变成1 // 此处不是让r变成b的引用,引用r声明并初始化后,r就不能再改为其它变量的引用 int &r2 = a; // 继续给a起别名 int &r3 = r; // 声明引用变量 r3,用r初始化 // 这个相当于 int& r3 = a; 因为 r 是 a 的别名 int *p = &r3 //当用&运算符获取一个引用的地址时,实际取出的是引用对应的变量的地址。p指向的是a
-
- 引用可做函数参数,但调用时只需传普通变量即可,在被调函数中改变引用变量的值,则改变的是实参的值
- 在变量声明时出现的&才是引用运算符(包括函数参数声明和函数返回类型的声明),其他地方出现的&则是地址操作符。
-
int &f(int &i1, int &); //引用参数,函数返回引用 int i; int &r = i; //引用 int *p = &i; //&取i的地址 cout << &p; //&取p的地址
-
- 引用对应变量的左值,代表变量的内存区域,实际是一种隐式指针,但与指针存在区别
- 指针必须通过 * 才能访问它所指向的内存单元,而引用于普通变量的访问方法差不多;
- 指针是一个变量,它有自己独立的内存区域,但引用只是某个变量的别名,甚至没有自己独立的内存区域,必须在定义时进行初始化,并且一经定义就不能作为其他变量的引用。
- 引用与数组。可以建立数组或数组元素的引用,但不能建立引用数组
-
int i = 0, a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, *b[10]; int (&ra)[10]; //正确,ra是具有10个元素的整形数组的引用 int &aa = a[0]; //正确,数组元素的引用 int *(&rpa)[10] = b; //正确,rpa是具有10个元素的整形指针数组的引用 int &ia[10] = a; //错误,ia是引用数组,每个数组元素都是引用 ra[3] = 0; //正确,数组引用的用法 rpa[3] = &i; //正确
-
- 引用与指针。可以建立指针的引用,但不能创建指向引用的指针
-
const char *s = "Hello"; //注意这里的const,const char*类型的值不能用于初始化char*类型的实体 const char *&rs = s; //无法用const char*类型的值初始化*char*&类型的引用(非常量限定) int i = 0, a[10]; int &*ip = i; //错误,ip是指向引用的指针 int *pi = &i; int *&pr = pi; //正确,pr是指针的引用
-
右值引用
右值引用就是绑到右值上的引用,只能绑定到即将销毁的对象上,如常量或表达式。用&&进行定义。右值引用可以方便地将引用的资源“移动”到另一个对象上。
double r = 10;
double &lr1 = r; //正确,变量名代表左值
double &lr2 = r + 10; //错误,引用只能是变量
double &&rr = r; //错误,变量名代表左值,而&&需要右值
double &&rr = r + 10; //正确,rr为表“r+10”计算结果,即20
/*计算表达式“r+10”的值,结果为20,系统创建double类型的无名对象,并将20保存在该对象中,
指定rr为该无名对象的右值引用,即无名对象的别名。假设没有右值引用,该操作是“使用无名对象的值23,用完后马上销毁该无名对象,收回它的内存区域”。如果以后要在用“r+10”,每次都重新计算
rr遵守变量的作用域和生存期规则,在定义它的{}的作用域有效,相当于延长了无名对象的生存期*/
附上三种swap函数(分别用传值、传指针和传引用实现)
//pass by value
#include <iostream>
using std::cout;
using std::endl;
void swap(int x, int y)
{
int t;
t = x; x = y; y = t; } int main() { int a = 5, b{10}; cout << "Before: a=" << a << " b=" << b << endl; swap(a, b); cout << "After: a=" << a << " b=" << b << endl; return 0; }
//pass by pointer
#include <iostream>
void swap(int *x, int *y)
{
int t;
t = *x;
*x = *y;
*y = t; } int main() { int a{5}, b{10}; std::cout << "Before: a=" << a << " b=" << b << std::endl; swap(&a, &b); std::cout << "After: a=" << a << " b=" << b << std::endl; return 0; }
//pass by reference
#include <iostream>
void swap(int &x, int &y)
{
int t;
t = x;
x = y;
y = t; } int main() { int a{5}, b{10}; std::cout << "Before: a=" << a << " b=" << b << std::endl; swap(a, b); std::cout << "After: a=" << a << " b=" << b << std::endl; system("Pause"); return 0; }