前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >还记得指针与引用吗?说下呗!

还记得指针与引用吗?说下呗!

作者头像
灿视学长
发布2021-05-28 15:04:44
发布2021-05-28 15:04:44
53300
代码可运行
举报
文章被收录于专栏:灿视学长灿视学长
运行总次数:0
代码可运行

分享知识与有趣的经验,欢迎关注一个在读博士奶爸!

百面计算机视觉第三版汇总

《百面计算机视觉汇总(超链接)持续更新,看过来!》

浅谈C++中指针和引用的区别

在C++中,我们常常使用到指针和引用,但对于它们的区别,很多C++的老手也容易混淆。

下面我们就来浅谈一下C++中指针和引用的区别,而这也是在面试时常会被问到的。

1.基础概念

(1)指针

在C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。

①创建指针变量
代码语言:javascript
代码运行次数:0
运行
复制
//格式:type *var-name;
int    *ip;    /* 一个整型的指针 */
double *dp;    /* 一个 double 型的指针 */
float  *fp;    /* 一个浮点型的指针 */
char   *ch;    /* 一个字符型的指针 */
(2)引用

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

①创建并初始化
代码语言:javascript
代码运行次数:0
运行
复制
//格式:type &var-name = var2;
//(注:var2为之前已定义的目标变量名)
int i = 17;
int &r = i;
double &s = d;
②引用的三个特点
  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。
  • 引用必须在创建时被初始化。

2.指针和引用的区别

(1)性质上的区别
①关于创建和初始化的不同

指针:任何时候均可被初始化,指针可以在任何时候指向到另一个对象,即指向其它的存储单元。

引用:创建时就需要初始化,一旦引用被初始化为一个对象,就不能被指向到另一个对象。

②关于实质

指针:是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元。

引用:跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已。对引用的操作与对变量直接操作完全一样。

例如:

代码语言:javascript
代码运行次数:0
运行
复制
//指针
int a=1;  //定义一个整型变量a
int *p=&a;  //定义一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址。
代码语言:javascript
代码运行次数:0
运行
复制
//引用
int a=1;  //定义一个整型变量a
int &b=a;  //定义一个引用b指向变量a,a和b是同一个东西,在内存占有同一个存储单元。
③关于空(NULL)的概念

指针:存在空指针。

引用:不存在空引用。

(注:空指针的定义和使用)

代码语言:javascript
代码运行次数:0
运行
复制
#include <iostream>

using namespace std;

int main ()
{
  int *ptr = NULL;

  cout << "ptr 的值是 " << ptr ;
 
  return 0;
}
代码语言:javascript
代码运行次数:0
运行
复制
//如需检查一个空指针,您可以使用 if 语句,如下所示:
if(ptr)     /* 如果 ptr 非空,则完成 */
if(!ptr)    /* 如果 ptr 为空,则完成 */
④关于多级

指针:可以有多级,如int *ip; /* 一个整型的指针 */int **p; /* 一个整型指针的指针 */

引用:只能是一级,如int a = 1;int &b = a; /* 一个整型变量的引用 */ 是合法的,但~~int &&a~~是不合法的。

⑤关于const

指针:可以有const指针。

引用:没有const引用。

⑥关于sizeof

"sizeof指针":得到的是指针本身的大小。

"sizeof引用":得到的是所指向的变量(对象)的大小。

⑦关于运算

指针和引用的自增(++)运算意义不一样。

(2)作为参数传递时的区别
①指针作为参数进行传递:

=> 如果要想达到也同时修改的目的的话,就得使用引用了。

代码语言:javascript
代码运行次数:0
运行
复制
#include<iostream>
using namespace std;

void swap(int *a,int *b)
{
  int temp=*a;
  *a=*b;
  *b=temp;
}

void test(int *p)
{
  int a=1;
  p=&a;
  cout<<p<<" "<<*p<<endl;
}

int main(void)
{
    int a=1,b=2;
    swap(&a,&b);
    cout<<a<<" "<<b<<endl;
    
    int *p=NULL;
    test(p);
    if(p==NULL)
    cout<<"指针p为NULL"<<endl;
    system("pause");
    return 0;
}
代码语言:javascript
代码运行次数:0
运行
复制
//运行结果为:
2 1       
0x61fddc 1
指针p为NULL

=> swap函数中,使用指针作为参数,传递过来的是实参的地址(即&a和&b)。因此使用*a实际上是取存储在实参内存单元里的数据,则对*a的赋值即是对传入实参的赋值,因此可以实现对实参进行改变的目的。

=> test函数中,事实上传递的也是地址,只不过传递的是地址。也就是说将指针变量作为参数进行传递时,事实上是“值传递”的方式,C语言中实参变量和形参变量之间的数据传递是单向的“值传递”方式。指针变量做函数参数也要遵循这一规则。当把指针作为参数进行传递时,也是将实参的一个拷贝传递给形参,即上面程序main函数中的p和test函数中使用的p不是同一个变量,存储2个变量p的单元也不相同(只是2个p指向同一个存储单元)。所以在test函数中对p进行修改,并不会影响到main函数中的p的值。

②将引用作为函数的参数进行传递。

在讲引用作为函数参数进行传递时,实质上传递的是实参本身,而不是实参的拷贝,对形参的修改就是对实参的修改。因此在用引用进行参数传递时,不仅节约时间,而且可以节约空间。

例如:

代码语言:javascript
代码运行次数:0
运行
复制
#include<iostream>
using namespace std;

void test(int *&p)
{
  int a=1;
  p=&a;
  cout<<p<<" "<<*p<<endl;
}

int main(void)
{
    int *p=NULL;
    test(p);
    if(p!=NULL)
    cout<<"指针p不为NULL"<<endl;
    system("pause");
    return 0;
}
代码语言:javascript
代码运行次数:0
运行
复制
//运行结果为:
0x22ff44 1
指针p不为NULL

这足以说明用引用进行参数传递时,事实上传递的是实参本身,而不是拷贝。

所以在上述要达到同时修改指针的目的的话,就得使用引用了。

总结

对于C++/C语言来说,如何使用指针是必考题,而与指针相关的引用也常会被作为面试题之一。能对它们进行区分辨别是很重要的。

引用

  • https://www.cnblogs.com/dolphin0520/archive/2011/04/03/2004869.html
  • https://www.runoob.com/cplusplus/cpp-references.html
  • https://baike.baidu.com/item/%E6%8C%87%E9%92%88/2878304?fr=aladdin

有趣的经验分享

- END -

大家好,我是灿视。目前是位算法工程师 + 创业者 + 奶爸的时间管理者!

我曾在百度与腾讯担任算法工程师,即将读博。我在19,20年连续推出两版《百面计算机视觉》,帮助了数百位同学们斩获了BAT等大小厂算法Offer。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 灿视学长 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 百面计算机视觉第三版汇总
  • 浅谈C++中指针和引用的区别
    • 1.基础概念
      • (1)指针
      • (2)引用
    • 2.指针和引用的区别
      • (1)性质上的区别
      • (2)作为参数传递时的区别
    • 总结
    • 引用
    • 有趣的经验分享
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档