C++ 引用深入理解
1、引用作为变量的别名存在,因此可以在一些场合代替指针。
引用相当于指针来说具有更好的可读性和实用性。
例如:
/* 编译环境 gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) */ #include <stdio.h> void sewp_C(int *a, int *b) //使用指针进行 a 和 b 之间的交换。 { int t; t = *a; *a = *b; *b = t; } void sewp_C_fun(int &a,int &b)//使用 引用实现 a 和 b之间的交换 { int t = a; a = b; b = t; } int main(int argc, char *argv[]) { int a = 1,b = 0; printf("Begin...\n"); sewp_C(&a,&b); printf("a = %d\tb = %d\n",a,b); //打印结果 a = 0 b = 1 sewp_C_fun(a,b); printf("a = %d\tb = %d\n",a,b); //打印结果 b = 1 a = 0 printf("End...\n"); return 0; }
运行结果:
Begin... a = 0 b = 1 a = 1 b = 0 End...
通过两种方式实现,两个数内容的交换。 使用指针调用函数则为:sewp_C(&a,&b); 而使用引用则为:sewp_C_fun(a,b); 这样看起来更加直观。
注意:在函数形参中的引用可以不用初始化。
特殊的引用:const 引用
在C++中声明const 引用格式: const Type & name = var;
const 引用可以让变量具备 只读属性
/* 编译环境 gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) */ #include <stdio.h> int main(int argc, char *argv[]) { printf("Begin...\n"); int a = 5; const int & b = a; int* p = (int*) &b; //b = 10;//错误 变量拥有只读属性 *p = 20; printf("a = %d\tb = %d\n",a,b); //打印结果 a = b = 20 printf("End...\n"); return 0; }
运行结果:
Begin... a = 20 b = 20 End...
如果将 const int & b = a; 替换成 :const int & b = 1; 这样将使用一个常量来初始化引用。
引用是否有自己的存储空间?
#include <stdio.h> struct Tqr { char & r; }; int main(int argc, char *argv[]) { char c = 'c'; char & rc = c; Tqr ref ={c}; int *p; printf("Begin...\n"); printf("sizeof(char &) = %d\n",(int)sizeof(char &)); // 打印变量char &所占用的大小 占用一个字节 printf("sizeof(rc) = %d\n",(int)sizeof(rc)); // rc 占用一个字节 printf("sizeof(Tqr) = %d\n",(int)sizeof(Tqr)); //占用4个字节 printf("sizeof(ref.r) = %d\n",(int)sizeof(ref.r)); //ref.r 占用1个字节 (字符变量) printf("sizeof(p) = %d\n",(int)sizeof(p)); printf("End...\n"); return 0; }
打印结果:
Begin... sizeof(char &) = 1 sizeof(rc) = 1 sizeof(Tqr) = 4 sizeof(ref.r) = 1 sizeof(p) = 4 End...
可以看出,Tqr 所占的空间为4 所以引用是占用4个字节的大小的。
所以可以猜测 引用 在C++中的实现就应该是使用指针来实现的。
引用的意义:其主要作用在大多数情况下是为了代替指针。
可以满足多数需要使用到指针的场合。
可以避开由于指针操作不当而带来的内存错误
简单易用,功能强大。
引用在函数返回值中的使用。
/* 编译环境 gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) */ #include <stdio.h> int& func1(void) { int a=5; return a; } //相当于c 语言中的 /* int * func1(void) { int a= 5; return &a; } */ int& func2(void) { static int b = 10; return b; } /* int * func2(void) { static b = 10; return &b; } */ int main(int argc, char *argv[]) { int &a = func1(); int &b = func2(); printf("Begin...\n"); //运行将会产生段错误 //产生段错误的原因是,因为 在func1 中a 是一个局部变量,在执行完成后将会被销毁 //a 指向一个被销毁的空间,自然会出错。而如果使用static 来修饰将不会出现段错误。 //因为使用static 会将变量声明为一个全局的变量。 printf("a = %d\tb = %d\n",a,b); //打印结果 a = 未知数 b = 10 printf("End...\n"); return 0; }
运行结果:
Begin...
Segmentation fault (core dumped)
在int a 替换为 static int a 后运行结果:(能够正常运行)
Begin... a = 5 b = 10 End...
小结:
引用作为变量别名存在目的是为了代替指针。
cons引用可以让变量获得只读属性。
引用的最终实现还是指针。
引用可以尽可能的避开内存错误。