普通引用
变量名实质上是一段连续存储空间的别名,是一个标号(门牌号) 。
程序中通过变量来申请并命名内存空间,通过变量的名字可以使用存储空间。
问题:对一段连续的内存空间只能取一个别名吗?
引用的概念
引用可以理解为已定义变量的别名
语法:Type& name = var;
例如:
int main
{
int a = 10;
int &b = a;
b = 20;
cout << a << endl;
}
输出结果:20
引用做函数参数
#include <iostream>
using namespace std;
struct Teacher
{
char name[20];
int age;
};
void printTec1(Teacher *);
void printTec2(Teacher &);
void printTec3(Teacher);
void printTec1(Teacher * pt)
{
cout << "printTec1 : " << pt->age << endl;
pt->age = 30;
}
void printTec2(Teacher &pt)
{
cout << "printTec2 : " << pt.age << endl;
pt.age = 40;
}
void printTec3(Teacher pt)
{
cout << "printTec3 : " << pt.age << endl;
pt.age = 50;
}
void main() {
Teacher t1;
t1.age = 20;
printTec1(&t1);// t1的地址赋值给形参指针变量pt
cout << "after printTec1 : " << t1.age << endl;
printTec2(t1);// pt是t1的别名,操作pt相当于直接操作t1
cout << "after printTec2 : " << t1.age << endl;
printTec3(t1);// pt是形参,t1拷贝一份数组给了pt,相当于pt=t1;修改pt不影响t1
cout << "after printTec3 : " << t1.age << endl;
cin.get();
}
结果:
引用做函数返回值
#include <iostream>
using namespace std;
int& fun1();
int& fun2();
int& fun1()
{
int a = 10;
return a;// 返回栈变量a
}
int& fun2()
{
static int a = 20;
return a;// 返回静态变量a
}
void main() {
int a = fun1(); // 使用普通变量来接,接的是a的值,没有问题
int &b = fun1();// 使用引用变量来接,接的是a的地址,a的地址已经被回收
int &c = fun2();
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
cin.get();
}
当函数返回值为引用时
1、若返回栈变量:不能成为其它引用的初始值,不能作为左值使用。
2、若返回静态变量或全局变量:可以成为其他引用的初始值,可作为左值使用。
指针的引用
#include <iostream>
using namespace std;
struct Teacher
{
char name[20];
int age;
};
void getTeacher(Teacher **tr)
{
Teacher *tmp = NULL;
tmp = (Teacher *)malloc(sizeof(Teacher));
tmp->age = 27;
*tr = tmp;
}
void getTeacher2(Teacher * &tr)
{
tr = (Teacher *)malloc(sizeof(Teacher));
tr->age = 29;
}
void main() {
Teacher *pt = NULL;
getTeacher(&pt);// 通过二级指针,间接改pt赋值
cout << pt->age << endl;
delete pt;
Teacher *pt2 = NULL;
getTeacher2(pt2);// 通过引用,直接修改pt2
cout << pt2->age << endl;
delete pt2;
cin.get();
}
引用的意义
1、引用作为其它变量的别名而存在,因此在一些场合可以代替指针
2、引用相对于指针来说具有更好的可读性和实用性
3、对比间接赋值成立的三个条件:①定义两个变量(实参、形参)、②建立关联(实参取地址传给形参)、③*形参间接修改实参的值。引用在实现上,只不过是帮我们完成了第②步,简化了第③步,将②③合二为一。
引用本质思考
定义引用时必须初始化,类似常量,一旦与某个变量关联起来,就将一直效忠于它。
引用所占用的空间大小与指针相同。
总结:
1、引用在C++中的内部实现是一个常指针,换句话说,引用在C++中是
下述代码的伪装表示:
Type &name <——>Type * const name
2、C++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同。
3、从使用的角度,引用会让人误会其只是一个别名,没有自己的存储空间。这是C++为了实用性而做出的细节隐藏。
何时使用引用
常量引用
常量引用两种初始化方式:
1、用变量初始化
int x = 20;
const int &y = x;
2、用字面量初始化
cont int &c = 30;