前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >令人疑惑的引用和指针

令人疑惑的引用和指针

作者头像
编程珠玑
发布2019-09-03 10:46:19
5700
发布2019-09-03 10:46:19
举报
文章被收录于专栏:编程珠玑编程珠玑

前言

在C++ 11中,新增了一种引用(本文都指左值引用)。从作用上来讲,它和指针类似,都可以用来间接引用对象,他们之间到底有什么异同呢?

引用

在分析之前我们先介绍一下引用。引用为对象起了一个别名。例如:

代码语言:javascript
复制
int a = 1024;
int &b = a;

这里的b就是指向a,相当于a的另外一个名字。b是一个引用,但并非一个对象,同时引用的类型都要和对象的类型严格匹配(在具有继承关系的类中是例外,这里不展开),因此有下面的操作:

代码语言:javascript
复制
int a = 1024;
int &b = a;
int &c = b;      //非法,b在此之前已经是引用,不能定义引用的引用
int &d = 1024;  //非法,引用类型的初始值必须是对象,而不能是字面值
const int &e = 1024 //合法,e为常量引用,只要能够转换成引用的类型,可以使用任何表达式作为初始值
double f = 1.024;
int &g = f;       //非法,类型不匹配

而对引用赋值,实际上是将值赋给了与引用绑定的对象,例如:

代码语言:javascript
复制
int h = 1024;
int &i = h;
i = 256;//将256赋给了h

同时,引用必须被初始化,下面的操作是非法的:

代码语言:javascript
复制
int &j;//非法,没有初始化

指针

学习过C的朋友可能对指针已经比较熟悉了,这里不占用较大篇幅。它存储的是一个地址,地址指向的是一个对象。例如:

代码语言:javascript
复制
int a = 0; //定义变量a
int *ptr = &a;定义int类型指针ptr,它存放变量a的地址

与引用类似,指针也实现了对其他对象的间接访问。同样的,它也要求指针的类型和指向的类型严格匹配。

引用和指针比较

引用不可为空,而指针可以

例如:

代码语言:javascript
复制
int &a; //非法,必须被初始化
int *p;//合法,但如果是非静态的指针变量,将拥有一个不确定的值

声明一个指针变量而不初始化是合法的,但是不建议这么做,原因可参见C语言入坑指南-被遗忘的初始化。正因如此,使用引用而非指针作为函数的参数是一个不错的选择,因为引用永远不为空,函数入口也就不需要做过多的检查,引用也就更富效率。

引用不是对象,而指针本身是对象

引用不是对象,它不能被再次赋值,而指针是可以的。例如:

代码语言:javascript
复制
int a = 1024;
int b = 2048;
int &c = a;
int *d = &a;
c = b; //其引用不会被再次赋值
d = &b;//合法,指针可以指向另外一个对象

也就是说,一旦引用了引用,就没法让它绑定到其他的对象。看起来引用还挺从一而终啊。

另外,可以有指向指针的指针,而不存在引用的引用。因为引用不是对象。

代码语言:javascript
复制
int a = 1024;
int &b = a;
int &&c = b;//非法
int *d = &a;
int **e = &d;//合法
引用指向对象本身,而指针指向的是对象的地址

定义一个指针的时候,编译器为他分配内存,而引用不会单独分配空间。 引用所代表的就是最初绑定的那个对象,因此使用sizeof分别作用于引用和指针时,前者得到的是引用所绑定对象大小,而后者得到的是指针占用空间大小(4或8字节),例如在64位的程序中:

代码语言:javascript
复制
/**假设有以下结构*/
typedef struct INFO
{
    int a;
    int b;
    char c;
}INFO;

INFO info = {0};//定义结构info
INFO &ref = info;//定义引用ref
INFO *ptr = &info;//定义指针ptr
sizeof(ref); //大小为INFO结构体占用空间大小,即12字节
sizeof(ptr); //占用大小为指针占用空间大小,即8字节
引用使用时无需解引用,而指针需要

例如:

代码语言:javascript
复制
int a = 1024;
int &ref = a;
int *p = &a;
ref = 10; //使用引用可直接使用,将所绑定对象的值修改
*p = 11;//使用指针需要解引用
作为参数时的差别

指针作为参数时,看起来是地址传参,实际上仍然传值,即将指针的一个拷贝作为实参,而由于指针指向的是一个对象,因此在函数内可以实现对指针所指向对象的内容进行改变。而引用作为参数时,实际上传递的对象本身,但又不需要拷贝,因为引用绑定的就是对象。

总结

从前面的内容来看,除了使用方法的差异意外,引用似乎像是弱化版的指针,是不是有点像指针常量呢?当然了,当你知道需要指向某个东西,而且绝不对改变其指向时,引用是一个不错的选择。

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

本文分享自 编程珠玑 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 引用
  • 指针
  • 引用和指针比较
    • 引用不可为空,而指针可以
      • 引用不是对象,而指针本身是对象
        • 引用指向对象本身,而指针指向的是对象的地址
          • 引用使用时无需解引用,而指针需要
            • 作为参数时的差别
            • 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档