我们先上两段简单的代码
1.cpp
#include<iostream>
using namespace std;
void f(int *a);
int main()
{
int a=1;
f(&a);
cout<<a;
}
void f(int *b)
{
*(b)=2;
}
运行结果:2
2.cpp
#include<iostream>
using namespace std;
void f(int &a);
int main()
{
int a=1;
f(a);
cout<<a;
}
void f(int &b)
{
b=2;
}
运行结果:2
在这里我们可以看到,两个产生的结果是一样的,都是把a的值从1变成了2,第一个代码的方法是通过c的指针来实现这种方法,第二个代码的方法是通过c++的引用来实现这种方法(注解:仅c++有这种用法,c语言是没有这种用法的,emm不要杠c代码是c++代码这个问题,当文件的后缀名是.c时会发生报错,但是后缀名是.cpp时是不会发生报错的)。
相同点:
二者都是指一块区域,都可以对这个区域的值进行更改,具有更改值的类似的作用。
不同点:
1.引用必须初始化,指针可以不初始化
举一个简单的例子
#include<iostream>
using namespace std;
int main()
{
int a=1;
int *p;
//int &b;这样的初始化就会发生报错
int &b=a; //这样的初始化就不会发生报错
}
指针在使用的开始,不一定需要指向一个具体的值,就是可以初始化之后不指向任何地方,但是在使用引用的时候,必须需要指向一个具体的值,如果不指向某个具体的对象就会发生报错。
2.引用必须与一个确定的单元关联,不可以指向空的地方,但是指针可以指向空的地方。
引用不能指向NULL的地方,但是指针可以,
#include<iostream>
using namespace std;
int main()
{
int *p=NULL;
// int &a=NULL; 加上这一行代码就会发生报错
}
3.引用没有占用空间,也就是只是换了个名字,在内存里面找不到引用这个地方的位置,但是指针是实实在在的存在的,需要占用一定的空间。也可以把引用视为指针常量,在编译器优化后它不占内存。
这个地方有点难以理解,一会说不占用空间,一会又说是一个指针常量(指针占用空间),这里解释一下,引用的空间是在代码编译的时候就给予了空间,但是指针的空间是代码在运行的时候给予的空间,也就是可以将引用看成一个const常量,他所需要的空间是在编译时期给予的一个空间,不属于代码的空间,所以称引用没有占用空间(这个空间是代码空间)。
4.指针的大小确定,引用的大小根据所引用的类型所确定
引用的大小与类型有关,如int类型它也是int,char类型它也是char,但是指针大小是具体的,它只负责指路,大小与类型无关。
5.指针主要在代码中,引用主要在编译过程中(仅针对于使用空间而言)
6.指针可以多级引用(即可以指针的指针),但是引用不可以。
7.引用只能指向一个对象,但是指针可以指向多个对象(或者理解为,指针所指向的对象是可以发生改变的)
#include<iostream>
using namespace std;
void f(int &a);
int main()
{
int a=1,b=2;
int &x=a;
cout<<x<<endl;
x=b;
cout<<x<<endl;
cout<<a<<endl;
}
我们通过看这个代码,我们可以发现,虽然把b的值给了x,但是a的值也发生了改变,所以x的引用的对象是没有发生改变的,x所指向的对象仍然是a,x=b这个代码只是把b的值赋给了x,但是x所引用的对象仍然是a而不是b。