1.1 引用的基本使用
- 作用:给变量起别名,新别名指向的是同一块内存。
- 语法:
数据类型 &别名 = 原名
#include<iostream> using namespace std; //引用,给变量起别名 int main(){ int a = 10; int &b = a; cout << "a = " << a << endl; cout << "b = " << b << endl; //a = 10 //b = 10 b = 100; cout << "a = " << a << endl; cout << "b = " << b << endl; //a = 100 //b = 100 system("pause"); return 0; }
1.2 引用的注意事项
- 引用必须初始化(上来就要说明是哪个变量的别名)
- 引用在初始化后,不可以改变该引用,如让b变成c的别名就不行了(如下栗子):
#include<iostream> using namespace std; //引用,给变量起别名 int main(){ int a = 10; //1.引用必须初始化 //int &b;//错误 int &b = a; //2.引用在初始化后,不可以改变 int c = 20; //想让b变成c的别名,这是赋值操作,而不是更改引用 b = c;//这里是b指向的内存赋值为20 cout << "a = " << a << endl;//20 cout << "a = " << b << endl;//20 cout << "a = " << c << endl;//20 system("pause"); return 0; }
1.3 引用作函数参数
函数传参,分为值传递(形参不能修饰实参)和地址传递。
- 引用作函数参数的作用:函数传参时,可用【引用】让形参修饰实参,这时就不用使用地址传递了。
- 优点:可以简化指针修改实参。
#include<iostream> using namespace std; //交换函数 //1.值传递 //2.地址传递 //3.引用传递 void mySwap01(int a, int b){ int temp = a; a = b; b = temp; cout << "swap01 a = " << a << endl; cout << "swap01 b = " << b << endl; cout << endl; } //2.地址传递,用指针接收地址 void mySwap02(int* a, int* b){ int temp = *a; *a = *b; *b = temp; cout << "swap02 a = " << a << endl; cout << "swap02 b = " << b << endl; cout << endl; } //引用传递,这里的形参的a是实参a的别名(只不过同名了) void mySwap03(int &a, int &b){ int temp = a; a = b; b = temp; cout << "swap03 a = " << a << endl; cout << "swap03 b = " << b << endl; cout << endl; } int main(){ int a = 10, b = 20; //1.值传递,形参不会修饰实参 //mySwap01(a, b); //2.地址传递,地址传递,形参会修饰实参 //mySwap02(&a, &b); //3.引用传递,形参也会修饰实参 mySwap03(a, b); cout << "a = " << a << endl; cout << "b = " << b << endl; system("pause"); return 0; }
小结:
引用传递,这里的形参的a是实参a的别名(只不过同名了)
通过引用参数产生的效果,和地址传递是一样的,但是【引用】的语法更加清楚。
1.4 引用作函数返回值
作用:引用是可以作为函数的返回值存在的。
注意:不要返回局部变量引用。
用法:函数调用作为左值。
(1)不要返回局部变量引用。栗子如下,第二次结果错误了,因为a的内存已经释放,而第一次正确是因为编译器作了保留。
#include<iostream> using namespace std; //1.不要返回局部变量的引用 int& test01(){ //局部变量存放在四区中的 栈区 int a = 10; return a; } int main(){ int &ref = test01(); //第一次正确是编译器做了保留 cout << "ref = " << ref << endl; //第二次结果错误,因为a的内存已经释放 cout << "ref = " << ref << endl; system("pause"); return 0; }
(2)函数调用作为左值。
现在不返回局部变量的引用,使用了static
后让函数返回静态变量的引用。
原名赋值为1000,别名访问也是1000。如果函数的返回值是一个引用,则这个函数的调用,可以作为左值。
#include<iostream> using namespace std; //1.不要返回局部变量的引用 int& test01(){ //局部变量存放在四区中的 栈区 int a = 10; return a; } //2.函数的调用可以作为左值 int& test02(){ static int a = 10; //静态变量,存放在全局区 //全局区上的数据在程序结束后系统释放 return a; } int main(){ //int &ref = test01(); //第一次正确是编译器做了保留 //cout << "ref = " << ref << endl; //第二次结果错误,因为a的内存已经释放 //cout << "ref = " << ref << endl; int &ref2 = test02(); cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl; test02() = 1000;//其实等于做了一个a=1000的赋值,ref2又是a的别名 cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl; system("pause"); return 0; }
1.5 常量引用
作用:常量引用主要用来修饰形参,防止误操作。
在函数形参列表中,可以加const
修饰形参,防止形参改变实参。
如下面的const
限定了ref
有只读性,无法修改,如果ref = 20
则会报错表达式必须是可修改的左值
。
#include<iostream> using namespace std; int main(){ //常量引用 //使用场景:用来修饰形参,防止误操作 int a = 10; //int &ref = 10; //引用必须引一块合法的内存空间 //加上const,编译器将代码修改为 int temp = 10; const int &ref = temp; const int &ref = 10; //引用必须引一块合法的内存空间 //表达式必须是可修改的左值 //ref = 20; system("pause"); return 0; }
(2)使用场景:用来修饰形参,防止误操作。
如下面的场景,只想让showValue函数打印val变量,但是由于形参用了引用,传入的a变量值也发生了改变,如果代码行多了,容易忘记这个a发生了改变(本意是不想让a改变),所以我们可以在形参上加上const,则会报错提示(更加安全):
所以当函数用引用时,修改了形参后,实参也会该,加上const则会报错提示,防止误对形参进行操作(如修改形参值后,外面的实参跟着改变了):
#include<iostream> using namespace std; //打印数据函数 void showValue(const int &val){ //val = 1000; cout << "val = " << val << endl; } int main(){ //常量引用 //使用场景:用来修饰形参,防止误操作 int a = 100; showValue(a); system("pause"); return 0; }