第5课 - 引用的本质分析
第5课 - 引用的本质分析
1. 引用的意义
(1)引用作为变量别名而存在,因此在一些场合可以代替指针
(2)引用相对于指针来说具有更好的可读性和实用性
注意: ① 一般在声明引用时,必须对其进行初始化 ② 函数中的引用形参不需要进行初始化!!!初始化发生在函数调用的时候。
2. 特殊的引用:const引用
(1)在 C++ 中可以声明 const 引用,形式如下:const Type& name = var; ,const引用让变量拥有只读属性
(2)当使用常量对 const 引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名
1 #include <stdio.h> 2 3 void Example() 4 { 5 printf("Example:\n"); 6 7 int a = 4; // i可以更改 8 const int& b = a; // b不可以更改 9 int* p = (int*)&b; 10 11 //b = 5; 12 13 *p = 5; 14 15 printf("a = %d\n", a); 16 printf("b = %d\n", b); 17 } 18 19 void Demo() 20 { 21 printf("Demo:\n"); 22 23 const int& c = 1; // 普通的引用int& c = 1; 编译器报错 24 25 int* p = (int*)&c; 26 27 //c = 5; 28 29 *p = 5; 30 31 printf("c = %d\n", c); 32 } 33 34 int main(int argc, char *argv[]) 35 { 36 Example(); 37 38 printf("\n"); 39 40 Demo(); 41 42 return 0; 43 }
3. 对引用的思考
引用有自己的存储空间吗?
1 #include <stdio.h> 2 3 struct TRef 4 { 5 char& r; 6 }; 7 8 int main(int argc, char *argv[]) 9 { 10 char c = 'c'; 11 12 char& rc = c; 13 14 TRef ref = { c }; 15 16 printf("sizeof(char&) = %d\n", sizeof(char&)); // 1 char型变量的别名 17 printf("sizeof(rc) = %d\n", sizeof(rc)); // sizeof(c) => 1 变量c的别名 18 19 printf("sizeof(TRef) = %d\n", sizeof(TRef)); // 4 结构体内的引用本质为指针,占4字节 20 printf("sizeof(ref.r) = %d\n", sizeof(ref.r)); // 1 char型变量的别名 21 22 return 0; 23 }
4. 引用的本质
(1)引用在C++ 中的内部实现是一个指针常量
(2)C++ 编译器在编译过程中用指针常量作为引用的内部实现,将int& a 转换为int* const a,因此引用所占用的空间大小与指针相同。
(3)从使用的角度,引用只是一个别名,编译器使用引用时,会转为*a,C++ 为了实用性而隐藏了引用的存储空间这一细节。
1 #include <stdio.h> 2 3 struct TRef 4 { 5 char* before; //4字节 6 char& ref;//4字节,本质是常量指针,会分配4字节的空间,相当于char* const ref; 7 char* after;//4字节 8 9 }; 10 11 12 int main() 13 { 14 char a = 'a'; 15 char& b = a; 16 char c ='c'; 17 18 TRef r = {&a, b, &c}; 19 20 printf("sizeof(r) = %d\n", sizeof(r)); //12 21 printf("sizeof(r.before) = %d\n", sizeof(r.before)); //4 22 printf("sizeof(r.after) = %d\n", sizeof(r.after)); //4 23 printf("&r.before = %p\n", &r.before); 24 printf("&r.after = %p\n", &r.after); //after和before相差8个字节,中间隔了个b引用所占用的空间 25 26 return 0; 27 }
5. 引用的意义
C++ 中的引用旨在大多数的情况下代替指针。
(1)功能性:可以满足多数需要使用指针的场合
(2)安全性:可以避开由于指针操作不当而带来的内存错误
(3)操作性:简单易用,又不失功能强大
1 #include <stdio.h> 2 3 int& demo() 4 { 5 int d = 0; 6 7 printf("demo: d = %d\n", d); //输出0 8 9 return d;//返回局部变量的引用,危险 10 } 11 12 int& func() 13 { 14 static int s = 0; 15 printf("func: s = %d\n", s);//输出0 16 17 return s; //合法,返回的是静态局部变量(位于全局存储区中的) 18 } 19 20 21 int main() 22 { 23 int& rd = demo(); 24 int& rs = func(); 25 26 printf("\n"); 27 printf("main: rd = %d\n", rd);//垃圾数值 28 printf("main: rs = %d\n", rs);//0,返回全局存储区中的s 29 printf("\n"); 30 31 return 0; 32 }
6. 小结
(1)引用作为变量别名而存在旨在代替指针
(2)const 引用可以使得变量具有只读属性
(3)引用在编译器内部使用指针常量实现
(4)引用的最终本质为指针
(5)引用可以尽可能的避开内存错误