前言
说到引用,对于Android开发工程师来说,肯定是不陌生的。比如Java中我们声明一个
Person person
,这里就是person
就是Person
的引用,可以让person = new Person("张三")
,即person
这个引用指向了"张三"这个对象。
引用概念
大家都知道,变量名实质上是一段连续存储空间的别名,是一个标号(门牌号),那么可能有人会问了,那能不能有多个别名呢?答案是肯定的,也就是说可以有多个引用,引用即变量的别名。
引用的作用
1.可以从函数中返回多个值。
2.可以修改实参值本身,不需要像值传递那样,函数处理的是实参数本地的副本。
3.传递地址可以节省复制大量数据的内存空间和时间。
大家看完引用的作用,可能一脸懵逼,但是这不要紧,当看完下面的例子,再回头来看,必然会有不一样的体会。
引用的初次相识
#include<iostream>
using namespace std;
void main() {
//变量名就相当于门牌号(也就是内存空间的别名,那可不可以有多个名字?)
int a = 10;
//b就是这个内存空间的另外一个别名
//C++中的一个引用(C中是没有引用的)
int &b = a;
cout << b << endl;
getchar();
}
这里变量b就是a的引用,用&加以标识。在C中是没有引用的概念的,引用是在C++中增加的。
引用的应用:
1.值交换
我们先来看看值交换的指针写法:
#include<iostream>
//指针值交换
void swap_1(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
再让我们来看看值交换的引用写法:
//引用值交换
void swap_2(int &a, int &b) {
int temp = a;
a = b;
b = temp;
}
主函数main调用值交换函数:
void main() {
int x = 10;
int y = 20;
printf("%d, %d\n", x, y);
//swap_1(&x, &y);
//a成了x的别名,b成了y的别名
swap_2(x, y);
printf("%d, %d\n", x, y);
getchar();
}
打印的结果:
10, 20
20, 10
这里验证了引用作用的第二条,引用改变的是参数本身,而不是参数的副本。因为这里我们打印的是变换之前x和y的值、变换之后x和y的值,如果不是改变参数本身,这里打印的应该都是10和20。
注意:
由于引用参数传递的是实参的地址,因此在调用函数时,不能向引用参数传递常数。比如此例中的swap_2(x, y),如果写成swap_2(10, 20)就是错误的。
2.代替二级指针
先来看看二级指针的例子:
先定义一个结构体:
#include<iostream>
struct Teacher {
char* name;
int age;
};
二级指针的写法
void getTeacher(Teacher **p) {
Teacher *temp = (Teacher*)malloc(sizeof(Teacher));
temp->age = 20;
*p = temp;
}
然后我们再来看看引用是怎样代替二级指针的:
void getTeacher(Teacher* &p) {
p = (Teacher*)malloc(sizeof(Teacher));
p->age = 40;
}
void main() {
Teacher *t = NULL;
//getTeacher(&t);
getTeacher(t);
printf("%d\n", t->age);
getchar();
}
打印的结果分别是20、40。
是不是简单了好多呢?
指针常量与常量指针
指针常量
#include<iostream>
void main() {
//指针常量,指针的常量:不能改变地址,但是可以修改它指向的内容
int a = 2, b = 3;
int *const p1 = &a;
//p1 = &b; //这样是不行的
*p1 = 4;
printf("%d\n", *p1);
}
指针常量,不能改变地址,但是可以修改它指向的内容
常量指针
#include<iostream>
void main() {
//常量指针,指向常量的指针:能改变地址,但是不可以修改它指向的内容
const int *p2 = &a;
p2 = &b;
//*p2 = 4; //这样是不行的
getchar();
}
常量指针,能改变地址,但是不可以修改它指向的内容
3.常引用
#include<iostream>
using namespace std;
void myPrintf(const int &d) {
cout << d << endl;
}
void main() {
//const int a;
//引用必须要有值,不能为空
//int &a = NULL;
//常引用
int a = 3, b = 4;
const int &c = a;
//c = b; //常引用不能再重新被赋值
//字面量
const int &d = 70;
myPrintf(c);
getchar();
}
注意:
1.常引用类似于Java中的final
2.引用必须要有值,不能为空
3.常引用不能再重新赋值
4.常引用作为函数的参数
5.常引用作为字面量来使用
指针是变量的地址,引用是变量的别名
#include<iostream>
using namespace std;
struct Teacher {
char name[20];
int age;
};
void main() {
Teacher t;
Teacher &t1 = t;
Teacher *t2 = &t;
cout << sizeof(t1) << endl; //24
cout << sizeof(t2) << endl; //4
getchar();
}
打印结果为:
24
4
由打印结果我们知道t1是24字节,t2是4字节,而该结构体是20(name) + 4(age) = 24字节,指针是4字节,我们就可以得出:
指针是变量的地址,引用是变量的别名
展望
本篇博客主要介绍了C++中的引用,接下来我将介绍C++中的类与函数,由于篇幅较长,故分为上、中、下三篇,敬请期待!