引用的基本使用
作用:给变量起别名
语法:数据类型 &別名 = 原名;
注意:操作别名时,相当于用原名进行操作,修改的是数据本身
引用注意事项
- 引用必须初始化
- 引用在初始化后,不可以改变
int a=10;
int b=20;
int &c=a; //给变量a起一个别名c
//引用在初始化后,不可以改变
c=b; //赋值操作,而不是更改引用。相当于a=b,意思是把20赋值给a
引用做函数参数
作用:函数传参时,可以利用引用的技术让形参操作实参
优点:可以简化指针,修改实参
//值传递
void swap01(int a,int b){
int temp=a;
a=b;
b=temp;
}
//地址传递
void swap02(int *a,int *b){
int temp=*a;
*a=*b;
*b=temp;
}
引用传递
void swap03(int &a,int &b){
int temp=a;
a=b;
b=temp;
}
int main(){
int a=10,b=20;
//值传递没有修改实参本身
swap01(a,b);
//地址传递可以对实参本身进行操作
swap02(&a,&b);
//引用传递可以对实参本身进行操作
swap01(a,b);
}
引用做函数的返回值
作用:引用是可以作为函数的返回值存在的
注意:不要返回局部变量引用
用法:函数调用作为左值
//引用做函数的返回值
//1、不要返回局部变量的引用
int& test01(){
int a=10; //创建局部变量a,存放在栈区,test01函数执行完会自动释放
return a;
}
//2、函数的调用可以作为左值
int& test02(){
static int b=20; //静态变量,存放在全局区,全局区上的数据在程序结束后系统释放
return b;
}
int main(){
//error
int &ans1=test01(); //ans1是test01中变量a的别名
//打印ans1就等价于打印a,然而a的内存已经释放
cout<<ans1<<endl;
int &ans2=test02();
cout<<ans2<<endl; //20
test02()=1000; //作为左值,相当于b=1000
cout<<ans2<<endl; //1000
}
引用的本质
本质:在c++内部,引用的本质是一个指针常量。
//发现是引用,转换为int* const ref = &a;
void func(int &ref){
ref=100; //ref是引用,转换为*ref = 100
}
int main(){
int a=10;
//自动转换为 int* const ref = &a;指针常量:指针指向不可改,也说明为什么引用不可更改
int &ref=a;
ref=20; //内部发现ref是引用,自动帮我们转换为:*ref = 20;
cout<<a<<endl;
cout<<ref<<endl;
func(a);
cout<<a<<endl;
cout<<ref<<endl;
}
结论:C++推荐用引用技术,因为语法方便,引用本质是指针常量,但是所有的指针操作编译器都帮我们做了。 另外函数的形参采用引用技术,可以减少内存的消耗,因为引用的本质是一个指针常量,原因和形参使用指针的时候一样。
常量引用
作用:常量引用主要用来修饰形参,防止误操作
在函数形参列表中,可以加const修饰形参,防止形参改变实参
//打印函数
void showValue(const int& value){
//value=200; //error,不可修改
cout<<value<<endl;
}
int main(){
int a=10;
int &ref1=a;
showValue(ref1);
//int &ref2=10; //error,引用必须引一块合法的内存空间
//加上const之后,编译器将代码修改为:int temp=10;const int &ref3=temp
//temp是一个临时变量
const int &ref3=10; //true
//ref3=20; //error,加入const之后变为只读,不可以修改
}