[C/C++]数组,指针,引用,到底有啥区别?

数组与指针

相信各位在初学的时候,指针和数组的概念还是比较泾渭分明的,但是学着学着,往往会感觉他们的界限越来越模糊,甚至产生“数组就是指针的”一种错觉。
但是很显然,这种想法是错误的,尽管数组名在值上与指针相同,但是如果我们采用VS去查看的,会发现他们的类型是不同:

int arr[3] = {1, 2, 3};
int *ptr = arr; 

arr的类型是int[3],而ptr的类型是int*,尽管大多数情况下,他们可以互相转化,但是还是有两个重要的操作符会给出不一样的结果:

  1. sizeof运算符,对于arr,会给出12,对于ptr,在32位g++下,给出4.

  2. &(取址运算符),我们可以看一下结果:

    运算符类型结果
    arrint[3]0xffc0e994
    &arrint[3]*0xffc0e994
    &arr[0]int*0xffc0e994
    ptrint*0xffc0e994
    &ptrint**0xffc0e990

    最为引人瞩目的是&arr和&ptr是不一致的

那么,为什么会有这样的不同呢?其实非常简单,什么是数组?数组是内存中一段连续的空间,他存储着一系列相同种类的元素。但是指针不同,他是一个存储着另一个对象的地址的对象。尽管我们在直接使用arr,也就是数组名的时候,编译器会解释为arr的地址,但是arr本身不是那个地址,而是那段连续的空间;ptr则不同,他本身就是地址。
另外,值得一提的是,数组类型是不支持拷贝初始化的,这也就决定了,数组不可能作为函数的参数(因为实参到形参必有一个拷贝初始化)。所以,我们看到的所有数组作为参数的函数调用,编译器会先帮助我们隐转为指针,然后进行调用,所以把数组作为参数传入函数之后,他的行为就与指针一致了。
那么,为什么数组不支持拷贝初始化呢?C++的数组继承自C,C是面向过程的语言,数组和数组的长度是分离的。这也就导致仅仅得知一个数组的情况下,无法得到它的长度。所以,自然无法拷贝。C++的vector类型内部具有长度,所以就可以拷贝初始化。

指针和引用

(下面讨论的,都是C++98里面经典的左值引用)
这也是一个非常让人迷惑的点,指针和引用看起来非常相似,但又如此不同,相信各位一定能把指针和引用的不同背的滚瓜烂熟:

  1. 最本质的不同:指针是一个对象(一块能存储数据并具有某种类型的内存空间),而引用仅仅是一个别名,这决定了引用与指针其他的不同
  2. 引用必须被初始化,但是指针不必。
  3. 存在空指针,但是没有空引用。
  4. 引用的创建和销毁不会调用构造与析构函数。
  5. 引用一旦与某个对象绑定便无法被绑定到其他变量上,但是指针是可以的。

但是,指针和引用有什么关系呢?答案是没有关系(笑)
在底层上看,引用和指针一样,都是通过变量的地址来进行访问的。但是编译器,也就是C++的语言层面对于引用做出了诸多限制。学习语言需要注意上层设计和底层设计(没有这种术语,我瞎说的),尽管底层上看引用和指针貌似一样,他肯定也得存在一个地址,但是我们的上层设计禁止了这一点,来保证“引用不是对象”的要求。所以,我们理解引用的时候,只需要知道,“引用不是对象,不是对象的地址,不是对象的拷贝,他仅仅是一个别名

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值