10 引用
作用:给变量起别名。引用是 C++ 相对 C 扩充的一个重要知识点,在函数参数和返回值中都会大量用到。
10.1 引用的基本使用
语法:数据类型 &别名 = 原名
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| #include <iostream> using namespace std;
int main() {
int a = 10;
int& b = a;
cout << "a = " << a << endl; cout << "b = " << b << endl;
b = 100;
cout << "a = " << a << endl; cout << "b = " << b << endl;
system("pause");
return 0; }
|
总结:引用和原变量操作的是==同一块内存空间==,给别名赋值,原名的值也会跟着改变。
10.2 引用注意事项
使用引用时有两点必须注意:
- 引用必须初始化
- 引用在初始化后,不可以改变指向(从头到尾只能指向同一个变量)
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <iostream> using namespace std;
int main() {
int a = 10; int b = 20;
int& c = a;
c = b;
cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl;
system("pause");
return 0; }
|
注意:c = b; 并不是让引用 c 改为指向 b,而是==把 b 的值赋给 c 引用的变量 a==,执行后 a、b、c 的值都是 20。
10.3 引用做函数参数
作用:函数传参时,可以利用引用的技术让形参修饰实参。
优点:可以简化指针修改实参。
通过交换函数案例,对比值传递、地址传递、引用传递三种方式的差异。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <iostream> using namespace std;
void mySwap01(int a, int b) { int temp = a; a = b; b = temp; }
void mySwap02(int* a, int* b) { int temp = *a; *a = *b; *b = temp; }
void mySwap03(int& a, int& b) { int temp = a; a = b; b = temp; }
int main() {
int a = 10; int b = 20;
mySwap01(a, b); cout << "值传递 a:" << a << " b:" << b << endl;
mySwap02(&a, &b); cout << "地址传递 a:" << a << " b:" << b << endl;
mySwap03(a, b); cout << "引用传递 a:" << a << " b:" << b << endl;
system("pause");
return 0; }
|
总结:引用传递和地址传递都能修改实参,而==引用的语法更清楚简单==:写起来像值传递,效果却像地址传递。
10.4 引用做函数返回值
作用:引用是可以作为函数的返回值存在的。
注意:不要返回局部变量的引用。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <iostream> using namespace std;
int& test01() { int a = 10; return a; }
int& test02() { static int a = 10; return a; }
int main() {
int& ref = test01(); cout << "ref = " << ref << endl; cout << "ref = " << ref << endl;
int& ref2 = test02(); cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl;
test02() = 1000; cout << "ref2 = " << ref2 << endl; cout << "ref2 = " << ref2 << endl;
system("pause");
return 0; }
|
总结:函数返回值是引用时,函数调用可以==作为左值==被赋值。
10.5 引用的本质
本质:引用的本质在 C++ 内部实现上是一个指针常量。
C++ 编译器在编译过程中,自动帮我们做了转换:
int& ref = a; 编译器转换为 int* const ref = &a;- 给引用赋值
ref = 20; 编译器转换为 *ref = 20;
指针常量的特点是指针的指向不可以修改,这也再次印证了引用一旦初始化就不可更改。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <iostream> using namespace std;
void func(int& ref) { ref = 100; }
int main() {
int a = 10;
int& ref = a; ref = 20;
cout << "a:" << a << endl; cout << "ref:" << ref << endl;
func(a); cout << "a:" << a << endl; cout << "ref:" << ref << endl;
system("pause");
return 0; }
|
提示:理解了「引用 = 指针常量」,10.2 中「引用不可更改指向」的规定就很好记了。
10.6 常量引用
作用:常量引用主要用来修饰形参,防止误操作。
在函数形参列表中,可以加 const 修饰形参,防止形参改变实参。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #include <iostream> using namespace std;
void showValue(const int& val) { cout << "val = " << val << endl; }
int main() {
int a = 10;
const int& ref = 10;
cout << "ref = " << ref << endl;
showValue(a);
system("pause");
return 0; }
|
总结:
- 引用的本质就是指针的封装,底层就是指针常量
- 常量引用既可以让形参更安全,又避免了值传递的拷贝开销
- 当函数的参数是引用且不需要修改实参时,加上 const 是好的习惯