从语法规则上说明:
指针变量存储的是某个实例(变量或对象)的地址;引用是某个实例的别名。
int a=10;
int *ip=&a;//指针ip存储的是变量a的地址
int &ra=a;//ra是a的别名
程序为指针变量分配内存空间,但是不为引用分配内存区域。
在32位系统上,指针大小为4字节
在64位系统上,指针大小为8字节
解引用是指针使用时要在前面加“ * ”,但是引用可以直接使用。
double a=12.23;
double *p=&a;
sizeof(p);//4字节
sizeof(*p);//8字节
指针变量的值可以发生改变(存储不同实例的地址),但是引用在定义时就被初始化,之后无法改变(不能是其他实例的引用)。
int a=10,b=20;
int *ip=&a;//ip指向a
ip=&b;//ip也可以指向b
int &ra=a;//ra一辈子都是a的别名
指针变量的值可以为空(指针可以指向NULL,nullptr),但是引用没有空引用。
int *ip=nullptr;
int &rp=*ip;//引用不能为空,但是可以间接为空
指针变量作为形参时需要测试它的合法性(判空NULL),但是引用不需要判空。
void func(int *p)
{
assert(p!=nullptr);//判空操作
}
void funb(int &p)
{
......
}
//引用要比指针安全,但是需要付出代价(能力收缩),不可以出现funb(nullptr)
对指针变量使用“sizeof”得到的是指针的大小,但是对引用变量使用“sizeof”得到的是变量的大小。
理论上指针的级数没有限制,但是引用只有一级。即不存在引用的引用的,但存在指针的指针。
char a=1;
char &ra=a;//ra为a的别名
char *cp=&a;//一级指针
char **ccp=&cp;//二级指针
sizeof(ccp);//4字节
sizeof(*ccp);//4字节
sizeof(*cp);//1字节
sizeof(ra);//1字节,引用要和类型保持一致
++引用与++指针变量的效果不同。对指针变量的操作:会使指针变量指向下一个实例(变量或者地址),而不是改变所指实例(对象或者对象)的内容;对引用的操作:直接作用于引用的实体。
int ar[]={1,2,3,4,5,6};
int *ip=&ar[0];
int &ra=ar[0];
++ip;//ip指向数组的下一个元素
++ra;//ar[0]+1
引用存在存在左值引用和右值引用之分,但是指针没有左值指针和右值指针之分。
int *ip;
int a=10;
int &ra=a;//左值引用
int &&rb=20;//右值引用
ip=&20;//err,指针不可以指向一个字面常量
ip=(int *)20;//此处可以强转,但是仍然不可以取地址
const int &cra=30;//常引用也可以引用一个字面常量
在使用模板时指针和引用有完全不同的表现形式:引用作为模板类可以得到实参的全部信息。
template<class T>
void funa(T x)//以值接收,无法接收到这个地址有多少个整型元素
{
cout<<sizeof(x)<<endl;//4字节
}
void funb(T &x)//只能接收一个左值引用,对于变量来说没有什么大的差别,但是对于数组来说,x将是数组ar的别名
{
cout<<sizeof(x)<<endl;//24字节
}
int main()
{
int ar[]={1,2,3,4,5,6};
funa(ar);//ar退化成指针
funb(ar);
return 0;
}
//总结:引用作为模板类来说,可以得到实参的全部信息
只有引用具有的:在模板类中,引用型别未定义。
template <class T>
void func(T &&x)//注意:此处不是右值引用!!!而是叫做引用型别未定义
{
......
}
int main()
{
int ar[]={1,2,3,4,5};
int a=10;
const int b=20;
func(a);//x为int &类型
func(b);//x为const int &类型
func(30);//x为int &&类型
func(ar);//x为int[5] &类型
}
可以定义一个数组元素是指针,但是不能定义一个数组元素是引用。
int *ar[10];//ok
int &br[10];//err
在容器中可以放值类型,指针类型,但是不可以放值类型。
std::vector<int>ievc;//ok
std::vector<int *>pievc;//ok
std::vector<int &>prievc;//err
从引用的本质说明:
通过汇编层次理解,引用是一个常性的指针(自身为常性的指针,我是你的别名,我就一辈子只指向你)。
int a =10;
int &ra =a;
int * const ra =&a;