一、引用的基本语法
作用:给变量起别名
语法:数据类型 &别名 = 原名
int a = 10;
int& b = a;
cout << a << " " << b << endl;
b = 20;
cout << a << " " << b << endl;
// int& c; // 错误,引用必须初始化
int c = 30;
b = c; // 引用一旦初始化就不能更改,这里是赋值操作,不是更改引用
输出:
10 10
20 20
注意:引用必须初始化,且引用在初始化后不可改变
二、引用作函数参数
作用:函数传参时,可以利用引用的技术让形参修饰实参
优点:可以简化指针修改实参
//1.值传递
void test1(int a,int b) {
int temp = a;
a = b;
b = temp;
}
//2.地址传递
void test2(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
//3.引用传递
void test3(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int a = 10, b = 20;
test1(a, b); //值传递,形参不会改变实参
cout << a << " " << b << endl;
test2(&a, &b); //地址传递,形参会改变实参
cout << a << " " << b << endl;
int c = 10, d = 20;
test3(c, d); //引用传递,形参会改变实参
cout << c << " " << d << endl;
}
输出:
10 20
20 10
20 10
引用传递的函数代码可以理解为,形参&a=c,形参&b=d,即a是c的别名,b是d的别名,在test3函数中对a、b的修改其实就是对c、d的修改。
三、引用作作函数的返回
1.不要返回局部变量的引用
2.函数的调用可以作为左值
int& test1() {
int a = 10; //局部变量存放在栈区中
return a; //返回局部变量的引用
}
int& test2() {
static int a = 10; //静态变量存放在全局区,数据在程序结束后系统释放
return a;
}
int main() {
int& r1 = test1();
cout << r1 << endl; //第一次输出为10,结果正确,因为编译器做了一次保留
cout << r1 << endl; //第二次输出为乱码,结果错误,因为a的内存已经释放
int& r2 = test2(); //r2为a的别名
cout << r2 << endl;
cout << r2 << endl; //输出仍为10,因为a的内存在程序结束后才会释放
test2() = 20; //如果函数的返回值为引用,这个函数调用可以作为左值,等价于a=20;
cout << r2 << endl; //r2是啊a的别名,输出为20
}
四、引用的本质
本质:引用在C++内部以指针常量的方式实现
指针常量的指针指向不可改变,这也就是为什么引用不可更改
int a = 10;
int& r = a;
编译器自动转换为 int* const r = &a;
r = 20;
编译器自动转换为 *r = 20;
五、常量引用
作用:用来修饰形参,防止误操作
int a = 10;
int& r = 10; //编译错误,引用必须引一块合法的内存空间
const int& r = 10; //加上const之后,编译器将代码修改为
int temp = 10; const int & r = temp; //引用临时变量,原名未知,只能使用别名r
r = 20; //编译错误。加入const之后变为只读,不可以修改
//加在形参前,若更改了数据会编译错误
void showValue(int &val){
cout<<val<<endl;
}