c++引用详解

铺垫:
变量名实质上是一段连续存储空间的别名,是一个标号
程序中通过变量来申请并命名内存空间
通过变量的名字可以使用存储空间
(能不能再名字的基础上在起个名字?)
概念:
1) 可以看做一个已定义变量的别名
引用是c++的语法范畴,不能再用C语言的思想去思考问题(间接修改)
属于c++编译器对c的扩展
 
引用做函数参数
普通引用在声明时必须用其他的变量进行初始化
【c++引用详解】引用作为函数参数声明时不进行初始化
#include<IOStream>using namespace std;//引用基本用法void main(){int a = 10; int &b = a; b = 100; printf("b:%dn", b); printf("a:%dn", a); cout << "hello...." << endl; system("pause"); return;}void main11(){ int a = 10; int &b = a; //int &c;//普通引用必须要初始化 system("pause");}void myswap01(int a, int b){ int c = 0; c = a; a = b; b = c;}void myswap02(int *a,int *b){ int c = 0; c = *a; *a = *b; *b = c;}void myswap03(int &a, int &b){ int c = 0; c = a; a = b; b = c;}voidmain(){ int x, y; x = 10; y = 20; myswap01(x, y); printf("x:%d,y:%dn", x, y); myswap02(&x, &y); printf("x:%d,y:%dn", x, y); myswap03(x, y); printf("x:%d,y:%dn", x, y); system("pause");}//复杂数据类型 的引用struct Teacher{ char name[64]; intage;};void printfT(Teacher *pT){ cout << pT->age << endl;}//pT是t1的别名,相当于修改了t1void printfT2(Teacher &pT){ cout << pT.age << endl;}//pT和t1是两个不同的变量void printfT3(Teacher pT){ cout << pT.age << endl;pT.age=45;//只会修改pT变量,不会修改t1变量}void main(){ Teacher t1; t1.age = 35; printfT(&t1); printfT2(t1);//pT是t1的别名printfT3(t1);//pT是形参,t1拷贝了一份数据,给pTprintf("t1.age:%dn",t1.age); cout << "hello...." << endl; system("pause"); return;}引用的意义
引用作为其他指针变量的别名而存在,因此在一些场合可以替代指针
引用相对于指针来说具有更好的可读性和实用性
引用的本质
c++编译器背后做了什么工作
单独定义的时候必须初始化--->很像常量
1)引用在c++内部实现是一个常指针
2)c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占的空间与指针相同
3)从使用的角度,引用会让人误会其只是一个别名,没有自己的储存空间,这是c++为了实用性做出的细节隐藏.
结论:当我们使用引用的语法时,我们不用去关心编译器引用是怎么做了
当我们分析奇怪的语法现象时,才去考虑编译器是怎么做的
#include<iostream>using namespace std;void main01(){ const int c1 = 10; int a = 10; int &b = a;//像常量 printf("&a:%dn", &a); printf("&b:%dn", &b);//a b就是同一块内存空间的门牌号依附于这个内存空间 cout << "hello.." << endl; system("pause"); return;}//普通引用有自己的空间吗?-->有,和指针所占的一样struct Teacher{ char name[64];//64 int age;//4 int &a;//4 int &b;//4};//引用的本质一个常量指针void main(){ printf("sizeof(Teacher):%dn", sizeof(Teacher); system("pause");}voidmodifyA(int &a1){ a1 = 100;}voidmodifyA2(int* const a1){ *a1 = 10;//*实参的地址,去间接修改实参的值}void main(){ int a = 10; modifyA(a);//指向这个函数调用的时候,我们程序员不需要取a的地址 printf("a:%dn", a); modifyA2(&a);//如果是指针 需要我们手工去取实参地址 printf("sizeof(Teacher):%dn", sizeof(Teacher)); system("pause");}//间接赋值//间接赋值成立的三个条件/*1 定义2个变量2 建立关系实参取地址传给形参3 形参间接修改实参的值*/voidmodifyA3(int *p){ *p = 190;//3}void main(){ int a = 10; int *p = NULL; //1 p = &a; *p = 100; {*p = 200; } modifyA3(&a);//2}//引用是间接赋值哪几个条件的组合?2编译器做了//123后2个条件写在一起了只不过2编译器做了函数返回值是引用(引用当左值)
c++引用使用时的难点:
当函数返回值为引用时,
若返回栈变量,不能成为其他引用的初始值,不能作为左值使用
若返回静态变量或全局变量 可以成为其他引用的初始值.
即可作为右值使用,也可作为左值使用
#include<iostream>using namespace std;int getAA1(){ int a; a = 10; return a;}//返回a的本身int& getAA2(){ int a; a = 10; return a;}int* getAA3(){ int a; a = 10; return &a;}void main01(){ int a1 = 0; int a2 = 0; a1 = getAA1(); a2 = getAA2(); int &a3= getAA2(); printf("a1:%dn", a1); printf("a2:%dn", a2); printf("a3:%dn", a3); cout << "hello.." << endl; system("pause"); return;}//返回静态/全局int j(){ static int a = 10; a++; return a;}int &j(){ static int a = 10; a++; return a;}void main(){ int a1 = 10; int a2 = 20; a1 = j1(); a2 = j2(); int &a3 = j2(); printf("a1:%dn", a1); printf("a2:%dn", a2); printf("a3:%dn", a3); cout << "hello.." << endl; system("pause"); return;}//函数当左值 //返回变量的值int g(){ static int a = 10; a++; return a;}//返回变量本身int &g(){ static int a = 10; a++; return a;}void main(){ //g1() = 100;//执行这个,函数返回值就是11.不成立err g2() = 100;//把上面的函数改成了100,所以这个就成立 system("pause");}


推荐阅读