引用,用途是对变量取别名,本质是一个指针常量。
1.初始化
&写在左侧为引用,写在右侧为取地址,引用用法:Type &别名 = 原名。
1 void test01(){ 2 int a = 10; 3 int &b = a; 4 b = 20; 5 cout << a << " " << b << endl; 6 }
引用必须初始化,另外初始化后不能再修改指向其他变量
1 void test02(){ 2 //int &a; //报错error C2530:引用必须初始化 3 int a = 10; 4 int &b = a; 5 int c = 20; 6 //int &b = c; 不能修改初始化的指向,会报错重定义 7 b = c; 8 }
对数组起别名
1 void test03(){ 2 //第一种方式 3 int a[10]; 4 for (int i = 0; i < 10; ++i){ 5 a[i] = i; 6 } 7 int(&arr)[10] = a; 8 9 //第二种方式,通过typedef 10 typedef int(INTARR)[10]; 11 INTARR &myAr = a; 12 }
2.参数传递方式
引用传参和地址传参的作用是一样的,都是为了修改变量值,其中引用后面的a和b相当于地址传参中的*a和*b。
1 void swap01(int *a, int *b){ 2 //---------- 3 //int c = 0; 4 //int *temp = &c; 5 //*temp = *a; 6 //*a = *b; 7 //*b = *temp; 8 //---------- 9 int temp = *a; 10 *a = *b; 11 *b = temp; 12 cout << *a << " " << *b << endl; 13 } 14 15 void swap02(int &a, int &b){ 16 int temp = 0; 17 temp = a; 18 a = b; 19 b = temp; 20 cout << a << " " << b << endl; 21 }
3.使用注意事项
(1)引用必须引一块合法的内存空间,也不是引用NULL
(2)不要返回局部自动变量的引用
1 int &test04(){ 2 //int &a = 10; 3 4 //------------ 5 //int c = 10; 6 //int &b = c; 7 //return b; 8 //------------ 9 10 int a = 10; 11 return a; 12 }
第2行显示了引用一块非法的内存空间,4-8行和10-11行是返回局部变量的引用,这种返回值可能会因为编译器的优化,使得第一次可以成功返回,但多返回几次就会报错。
(3)函数的返回值为引用,这个函数调用可以作为左值
int main(){ test04() = 20; //相当于a = 20 int a = test04(); }
4.引用的本质
引用的本质是指针常量。
1 Type &ref = val; //Type *const ref = &val 2 3 int a = 10; 4 int &b = a;//自动转换为int *const b = &a,指针常量必须初始化,因此引用必须初始化 5 b = 20; //内部发现b是引用,自动帮我们转换:*b = 20;
5.指针引用
一般的二级指针 Type **p可以改写成Type *&p
1 #include <iostream> 2 using namespace std; 3 4 struct Person{ 5 int age; 6 }; 7 8 void allocMemory(Person **p){ 9 *p = (Person*)malloc(sizeof(Person)); 10 (*p)->age = 100; 11 } 12 13 void test05(){ 14 Person *p = NULL; 15 allocMemory(&p); 16 cout << p->age << endl; 17 } 18 19 void allocMemoryRef(Person *&p){ 20 p = (Person*)malloc(sizeof(Person)); 21 p->age = 200; 22 } 23 24 void test06(){ 25 Person *p = NULL; 26 allocMemoryRef(p); 27 cout << p->age << endl; 28 } 29 30 int main(){ 31 32 test05(); 33 test06(); 34 system("pause"); 35 return 0; 36 }
6.常量引用
通过一个例子引入常量引用
1 void test(){ 2 //int &a = 10; // 引用不合法的空间 3 const int &a = 10; //会分配内存,编译器进行处理 int tmp = 10; const int &a = tmp; 4 int *p = (int *)&a; 5 *p = 100; 6 cout << a << endl; //a被修改 7 }
其实上面的代码使用的比较少,一般多用const Type &ref进行形参使用,使用常量引用形参的好处:(1)使用引用作为形参,不会产生新的变量,减少形参和实参传递的开销;(2)使用引用可能会导致实参随着形参的改变而改变。声明为const之后就会消除这种副作用。