C++中指针和引用的区别、以及引用和取地址符&的区别

144 篇文章 6 订阅

一. 指针和引用的区别

对于指针来说,它是一个地址,这个地址是一个数值,那么就意味这个数值可以为0(空指针),也可以为其他,即指针可以不指向任何东西。

而对于引用来说,他是一个外号,外号一定是“某个存在物体”的外号,所以引用不能为空,即不能存在空引用。例如我们给小明起了个外号:明明,那我们说明明的时候,就是说小明。对引用的操作与对变量直接操作完全一样。

根据以上可知指针和引用的一个重要不同:指针可以为空,引用不能为空。这就意味着我们拿到一个引用的时候,是不需要判断引用是否为空的,而拿到一个指针的时候,我们则需要判断它是否为空。这点经常在判断函数参数是否有效的时候使用。
例如:

void fun1(int *point)
{
     // 为了代码的稳健和安全,我们需要判断指针是否有效,通常做法是判断指针是否为
     // 空,其他的判断就需要根据函数的具体功能来判断了
     if(!point)
     {
        return;
     }
     // 函数实现
}

void fun2(int &refence)
{
     // 在这里,我们就不用担心refence是否为空
}


引用修饰函数参数还可以提高效率,例子如下:

Class Object
{// 实现省略,只需要知道我们在这里声明了一个类,在下面我们要将这个类的对象作为
 // 函数参数类型来使用};
void fun1(Object obj)
{
     // 此函数声明中,obj是值传递,会产生一个临时对象
}
void fun2(Object &obj)
{
    // 我们不用检查obj是否为空,同时,使用引用传递,可以避免临时对象
}
void fun3(Object* obj)
{
    if(!obj)...
    // 需要检查obj是否为空,同时,可以避免临时对象
}

我们根据前面的描述,还可以知道指针可以多次赋值,即在某时刻可以指向地址1,换个时候可以指向地址2,例如:

int a = 0;
int b = 1;
int *point = NULL;
point = &a;     // 在某个时刻,指针可以指向a
point = &b;     // 换个时刻,指针可以指向b

而引用则不同,引用只能在初始化的时候就赋好值,之后就不能改变了,用外号的例子来说就是"明明"这个外号在出现的时候就是代指小明,之后“明明”这个外号就绑在小明身上了,它不能过段时间换成小暗的外号。对reference_mingming(不是&reference_mingming)的操作,就是对xiaoming的操作。代码如下:

int xiaoming = 1;
int &refence_mingming = xiaoming;
int xiaoan = 2;
refence_mingming = xiaoan;           // error,引用不能换了

由以上可以,当我们需要某个是否指向为空的时候,我们就需要使用指针了,还有指向的对象需要变化的时候,我们也需要使用指针。其他地方一般推荐引用。

更多内容可以参见<more effective C++>第一条:引用和指针的区别。

二. 取地址符&和引用的关键字的区别:

作引用的关键字时:

类型名  &  别名 = var;

1.定义的时候必须初始化,即& 前面有类名或类型名,&别名后面一定带 “=” (在= 左边);

2.&后面的别名是新的名字,之前不存在

3. 引用在使用的时候,只用别名,不再使用&,也就是说对于一个引用,其关键字&只出现一次(在定义的时候)。

4.C++中“引用”的概念就是要作为对象的别名,尽管其自身也会占用内存(此处不同意匿名用户,引用最终会被编译为指针,因此占用内存),但作为对象别名,它要拥有对象本身所有的功能,因此取地址时,取的是对象的地址而不是自己的地址——C++就是这样设计的,要不然很多事情你都干不了.

5.对引用的操作与对变量直接操作完全一样,则对引用的取地址操作,等同于对变量的取地址,如下图中所示cout<<&c和cout<<&a是一样的。这个不太好理解(c本身也应该有地址吧,这是C++规定的),“&引用” 和“&取地址符”是一样的。

 

&取地址时:

如果&是取址运算符,也就意味着取一个变量的地址并付给指针变量。&后面紧跟的是变量(已存在);

所以依据&后面的变量名是否已经存在,也很容易判断是引用还是取地址符。

下面给出一个例子来说明引用和指针的区别,以及引用的地址的问题。

int a=1;
int &c=a;
int *b=&a;
int main()
{
	cout<<c<<endl;  //此时的c就是a,输出1
	cout<<&c<<endl;  //输出的是c的存储地址也就是a的地址
	cout<<&a<<endl; //和cout<<&c<<endl;和上一个代码一样
	cout<<*&c<<endl;  //*直接取这个地址的结果,也就是输出1,也就是a也是c
	cout<<b<<endl;   //b是指针,指向的是a的地址,输出就是a的地址
	cout<<*b<<endl;  //指针指向地址里面结果,也就是输出1咯
	system("pause");
}

 

  • 11
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值