目录
五、引用的使用场景
一、什么是引用?
引用实际上是给一个变量起别名,编译器不会为引用变量开辟一个新的内存空间,变量和它的引用变量共用同一块内存空间。就好比水浒传中的李逵有的别名,既可以叫做黑旋风,也可以叫铁牛,实际上都是同一个人。
语法:数据类型& 别名=原名
int main()
{
int a = 10;
int& b = a;//b是a的别名
cout << "a=" << a << endl;//两者打印的结果是一样的
cout << "b=" << b << endl;
cout << "a的地址" << &a << endl;//两者地址是一样的
cout << "b的地址" << &b << endl;
return 0;
}
二、引用的注意事项
1、引用必须初始化
2、一个变量有多个引用
3、引用在初始化后,不可以改变其指向
int main()
{
//1、引用必须初始化
//int& a;
//2. 一个变量可以有多个引用
//int a = 10;
//int& b = a;
//int& c = a;
//3、引用在初始化后,不可以改变其指向
//int a = 20;
//int b = 10;
//int& c = a;//一旦初始化后,就不能修改
//c = b;//赋值操作
return 0;
}
三、引用的本质
引用本质就是一个指针常量,引用一旦初始化,其指向就不可以发生改变。
int main()
{
int a = 10;
//自定转化为int* const b=&a;
//指针常量是指针的指向不可以改
//也就说明了引用为什么不可以改
int& b = a;
//编译器发现b是引用,自动帮我们转化为*b=20;
b = 20;
}
四、常量引用
当函数参数是引用的时候,有时需要用到常量引用,涉及到权限以及防止误操作。
权限方面不能放大,只能缩小。
例如一个变量是一个可读可写的权限,可以修改为只读的权限。
一个变量是只读的权限,不能修改为可读可写的权限。
int main()
{
//权限平移
int a = 10;
int& b = a;
//权限不能放大
const int c = 20;//c是只读
//int& d=c;//d是可读可写 c是只读,错误
const int& d = c;//d是只读 权限平移
//权限可以缩小
int e = 30;//e可读可写
const int& f = e;//f只读
return 0;
}
如果使用引用传参,函数内如果不改变参数,建议使用const引用传参
例如一个函数实现打印的功能,使用引用传参,目的是为了打印,而函数内部依然可以改变形参,可能会涉及到误操作,可以加const修饰形参,防止形参改变实参。
//利用常量引用防止误操作修改实参
void ShowValue(const int& b)
{
//b+=10;//误操作,改变了实参
// 加入const之后,都是只读的权限,避免通过引用修改实参
cout << b << endl;
}
int main()
{
int a = 10;
//该函数只是实现打印数据功能
ShowValue(a);
return 0;
}
五、引用的使用场景
1、引用做参数
作用:函数传参时,可以利用引用让形参修饰实参
优点:可以简化指针修改实参
总结:通过引用参数产生的效果同按地址传递是一样的,引用的语法更简单清楚
//引用做函数参数
void mySwap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
int main()
{
int a = 10;
int b = 20;
cout << "交换前a=" << a << endl;
cout << "交换前b=" << b << endl;
mySwap(a, b);
cout << "交换后a=" << a << endl;
cout << "交换后b=" << b << endl;
return 0;
}
//交换前a=10 b=20
//交换后a=20 b=10
2、引用做返回值
作用:引用是可以作为函数的返回值的
注意:不能返回局部变量引用,可以返回静态变量引用
原因:局部变量是存放在栈区的,出了作用域便会销毁,而静态变量是存放在静态区的,
静态区上的数据在程序结束后系统释放
//这个程序使用引用返回本质是不对的,返回值没有保障
int& count()
{
int n = 0;//n存放在栈区,出了作用域就被销毁
n++;
return n;
}
int main()
{
int& ret = count();
cout << ret << endl;
cout << ret << endl;
return 0;
}
//这个场景可以使用传引用返回
int& count()
{
static int n = 0;//static修饰的变量n存放在静态区
n++;
return n;
}
int main()
{
int& ret = count();
cout << ret << endl;
cout << ret << endl;
return 0;
}
六、引用和指针的区别
语法角度:引用是没有开空间的,指针有开空间
int main()
{
int a = 10;
//语法角度,ra没有开空间
int& ra = a;
ra = 20;
//语法角度,pa开了4or8byte空间
int* pa =&a;
*pa = 20;
return 0;
}
底层角度:引用和指针都是开了空间的
引用和指针的不同点:
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 指针使用更强大,更危险,更复杂,引用比指针使用起来相对更安全,更简单,但相对局限