C++中的引用
来源:互联网 发布:文字录入赚钱软件 编辑:程序博客网 时间:2024/05/02 05:06
C++中的引用
标签: c++
1. 变量名回顾
+ 变量名实质上是一段连续存储空间的别名,是一个标号 + 程序中通过变量来申请并命名内存空间 + 通过变量的名字可以使用存储空间
2. c++的引用
引用是C++的概念,属于C++编译器对C的扩展。
int main(){ int a = 0; int &b = a; //int * const b = &a b = 11; //*b = 11; return 0;}/**结论:请不要用C的语法考虑 b=11*/
引用概念: + 在C++中新增加了引用的概念 + 引用可以看作一个已定义变量的别名 + 引用的语法:Type& name = var; + 引用做函数参数呢?(引用作为函数参数声明时不进行初始化)
#include <iostream>using namespace std;int main(){ int a = 10; int &b = a; //b是a的别名,请问c++编译器后面做了什么工作? b = 11; cout<<"b--->"<< a << endl; printf("a: %d\n", a); printf("b: %d\n", b); printf("&a: %d\n", &a); printf("&b: %d\n", &b); //对同一块内存空间可以取多个别名 system("pause"); return 0;}/**b--->11a: 11b: 11&a: 3798852&b: 3798852*/
结论:1. 普通引用在声明时必须用其它的变量进行初始化 为什么必须初始化? --> 结论:很像一个只读的常量
3. 引用的意义
1. 引用作为其它变量的别名而存在,因此在一些场合可以代替指针 2. 引用相对于指针来说具有更好的可读性和实用性 比较下面实现同样功能的代码:
#include <iostream>using namespace std;int swap(int &a, int &b){ int c = 0; c = a; a = b; b = c;}int swap(int *a, int *b){ int c = 0; c = *a; *a = *b; *b = c;}//引用和左值进行绑定时,将设计出高质量的程序//引用像一个常量,能起到指针的作用//引用和指针有关系吗?//引用有内存空间void main(){ int a = 10; int a1 = 20; int &b = a; // type & 引用的名字 = 被引用的变量 char buf[100]; //在使用的时候,引用相当于变量的别名 b = 11; // *b = 11; swap(a, b); swap(&a, &b);}
4. 关于引用
普通引用有自己的内存空间吗?回答是肯定的:
#include <iostream>using namespace std;struct Teacer { int &a; int &b;};int main(){ printf("sizeof(Teacher) %d\n", sizeof(Teacer)); system("pause"); return 0;}/**结果是:sizeof(Teacher) 8*/
我们可以得出结论:引用是一个有地址,引用是常量。 引用的本质: + 引用在C++中的内部实现是一个常指针 Type& name <--> Type* const name + C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。 + 从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏 请仔细对比间接赋值成立的三个条件: 1. 定义两个变量 (一个实参一个形参) 2. 建立关联,实参取地址传给形参: p = &a; 3. 利用*p形参去间接的修改实参的值 结论:引用在实现上,只不过是把间接赋值成立的三个条件的后两步合二为一。当实参传给形参引用的时候,只不过是c++编译器帮我们程序员手工取了一个实参地址,传给了形参引用(常量指针)。
5. 引用的细节问题
看下面的代码:
#include <iostream>using namespace std;int myf01(){ int a; a = 11; return a;}int& myf02(){ int a; a = 11; return a;}int& myf03(){ int b; b = 22; return b;}void main(){ int b1 = myf01(); printf("b1 = %d \n", b1); int b2 = myf02(); //返回一个值,然后赋给b2 /** 还原现场是这样的: b2 = p(p是a的别名),因此实现了赋值操作,执行完了这一步myf02()里面的变量才被清理 */ printf("b2 = %d \n", b2); int &b3 = myf03(); //b3是返回时的引用 /** b3只是一个引用相当于int * const b3 b3并没有记录下a的值,只记住了地址,函数运行完成了之后myf03()里面的局部变量被清理了(也可能没有),有可能会出错 */ printf("b3 = %d \n", b3); //b3是一个引用,c++编译器会帮我们执行*p操作 system("pause");}/**结果如下:b1 = 11b2 = 11b3 = 22 其实b3大多时候应该是一个未知的数,不过本人的64位机器上运行正常,这是因为还没有清理内存的缘故。*/
如果函数里面的值生命周期比较长,结果会有所不同:
#include <iostream>using namespace std;int& myj01(){ static int a; //a分配在全局区,生命周期和程序一致 a = 10; return a;}void main(){ int b1 = myj01(); printf("b1 = %d \n", b1); int b2 = myj01(); //返回一个值,然后赋给b2 printf("b2 = %d \n", b2); int &b3 = myj01(); //b3是返回时的引用 printf("b3 = %d \n", b3); //b3是一个引用,c++编译器会帮我们执行*p操作 system("pause");}/**结果如下:b1 = 10b2 = 10b3 = 10原因也很简单,那就是函数myj01运行完后a并未被清理掉,因此不会出错。*/
当然,也可以这样:
#include <iostream>using namespace std;int& myA(int &a){ a++; return a;}void main(){ int b = 10; int b1 = myA(b); int b2 = myA(b); int b3 = myA(b); printf("b1 = %d \n", b1); printf("b2 = %d \n", b2); printf("b3 = %d \n", b3); //b3是一个引用,c++编译器会帮我们执行*p操作 system("pause");}/**结果如下:b1 = 11b2 = 12b3 = 13解释和前面的例子是一样的。*/
我们需要特别注意下面的代码:
#include <iostream>using namespace std;struct AdvTeacher{ char name[32]; int age;};void getTeacher01(AdvTeacher **p){ AdvTeacher *ptmp = (AdvTeacher *)malloc(sizeof(AdvTeacher)); ptmp->age = 30; *p = ptmp;}//这个是结构体变量指针的引用,指针的引用//p是t2的别名void getTeacher02(AdvTeacher *&p) //和上面函数的作用一致{/**&p <--> * const p */ p = (AdvTeacher *)malloc(sizeof(AdvTeacher)); p->age = 30;}//如果不加引用,那么myT3会拷贝给p,修改p和myT3没有任何关系//加了引用,p是myT3的别名,修改p和修改myT3一样void getTeacher03(AdvTeacher &p) //和上面函数的作用一致{ p.age = 11;}void main(){ AdvTeacher *t1 = NULL; AdvTeacher *t2 = NULL; getTeacher01(&t1); getTeacher02(t2); { AdvTeacher myT3; myT3.age = 10; getTeacher03(myT3); } system("pause");}
引用可以做左值:
#include <iostream>using namespace std;//static int a = 10;将a变成一个状态变量//a初始化的时候为10,只会初始化一次int& myg(){ static int a = 10; //分配在全局区 printf("a = %d\n", a); return a;}void main(){ myg() = 11; //引用当做左值 myg(); system("pause");}/**结果如下:a = 10a = 11*/
常引用: + 常引用 Const int &e 相当于 const int * const e + 普通引用 int &e 相当于 int *const e 有两种方法对常引用进行初始化: + 让变量初始化const引用如 int a = 10; const int &b = a; + 使用字面量初始化const引用 const int &c = 10; 虽然这在普通引用里不行,但在常引用里面行得通。当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名,使用常量对const引用初始化后将生成一个只读变量。
#include <iostream>using namespace std;struct AdvTeacher{ char name[32]; int age;};//const &void getTeacher(const AdvTeacher &p) //和上面函数的作用一致{ //只能读,不能写 //p.age = 11; //常引用不能被修改 printf("age = %d \n", p.age);}//1. const引用的作用,让变量所指向的内存空间只读//2. 给const引用初始化,有两种方法//让变量初始化const引用void main(){ //int &a = 10; //10没法取地址,因此会出错 int b = 10; const int &c = b; //c = 11; //不能通过c去间接修改b b = 12; //可以修改b的值 //const引用的第二种初始化方法 const int &d = 10; //对10另外分配一块内存空间 printf("&d = %d\n", &d); system("pause");}/**结果因人而异,不过肯定的是10分配了空间&d = 1506876*/
6. c++引用需要注意的地方
当函数返回值为引用时 + 若返回栈内变量的引用,则不能用其成为其它引用的初始值,且不能将其作为左值使用。 + 若返回静态变量或全局变量,可以成为其他引用的初始值,即可作为右值使用,也可作为左值使用。
0 0
- c语言中的引用
- 【C++】:C++中的引用
- 深入探讨C 中的引用
- 深入探讨C 中的引用
- C++/CLI中的引用类型
- 深入探讨C 中的引用
- C++中的引用
- [C++]C++中的引用(转)
- 【引用】C中的类型转换
- C语言中的引用调用
- 深入探讨c++中的引用
- C/C++中的指针、引用和JAVA中的引用
- C/C++中的引用和指针
- c语言形参中的引用变量
- C/C++中的引用和指针
- C/C++中的引用和指针
- c语言实现cpp中的引用传递
- C和C++中的引用和指针
- I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之声卡驱动移植
- p124 第三章 第42题 潘璠
- p value 是什么
- 的非方将航股将工尽给丫
- 关于企业账号
- C++中的引用
- 自定义BaseAdapter完成ListView列表单选功能
- HDU ACM 4506 小明系列故事——师兄帮帮忙 ->简单快速幂
- 招聘一位优秀的工程师
- 如何运行导入eclipse的web工程
- 黑马程序员——c语言基础:指针函数和函数指针
- 控制td中的内容多出td长度的部分用省略号表示
- c++对于c的加强
- DuiVision开发教程(10)-皮肤选择窗口