首先,我们分别得说明,指针和引用分别是什么:
指针:它是对一个类型的对象而言的.假如有一个T类型的对象a,那么*T类型就是一个指针类型,它代表了T类型的对象所占据内存的地址。
引用:它是一个T类型对象的别名。因此不能脱离实际对象而存在。
一:指针和引用的区别:
1.引用不能为NULL,而指针可以为NULL。
当引用进行声明的时候,必须进行初始化,否则,就会出现如下图的情况。
当然,你要是说有个人,写如下的代码:
那我只能说,这就是GG思密达,这个引用根本木有意义,可能会输出任何东西,但我在Dev里面尝试了一把,直接就崩溃了。
2.引用必须有初始化值,而指针不必有。
这其实和上一条是一致的。引用既然只是个别名,那么必然就得有其所依附的类型的对象,否则只有别名,没有主名,就不知道引用到哪里去了。
当然,指针虽说不一定要初始化,但是我们在声明指针的时候,最好能把它设置成NULL,这样我们在检验的时候,才能更好的判断其有效性。
3.引用不必做有效性检查,但是指针是必须的。
这个性质其实又继承于区别2。有效性检查通常就是看,这个值到底是不是合法的?在函数里是不是可用的?由于引用不能是NULL,那就是说,其必然依附于一个类型T的对象,则在传入参数的时候,不需要进行有效性检验。
但是指针就很明显不一样了。上一条说过,如果暂时用不上,指针最好初始化为NULL。那么,在将指针传进函数的时候,指针很有可能什么都不指向。(当然,这比指针指向了一个乱七八糟的东西,变成野指针,还是要好点的,毕竟NULL指针还是容易判断的)。因此,我们必须在使用这个指针之前,先测试一下,看看指针是否为NULL,才能继续用下去。
4.引用至死不渝,指针到处乱顶
引用就像童养媳,从出生开始,我们就规定它,必须是某个类型的对象的别名,还不能改变。管它是啥对象,黑的白的,高的矮的,说是它了,那就是它了。好像是个指腹为婚的女孩,而且对方还必须得比你先出生。等到出生了,引用就得嫁给那个对象,一辈子就是那个对象的别名,想改也改不了。这很像古代中国女子所受到的束缚。当然我们必须得说,通过引用,我们是能够改变其对象本身的,就好像即便是古代的老婆,枕头风的威力还是不能小觑。
指针就像是个汉子,它可以不指向任何对象,而即便指向了某个对象,也可以换,不同时间内可以指向不同的对象。所以,我们可以看到,汉子四十没对象,只要条件还不错,就叫钻石王老五,妹子要四十了还没嫁,那家里人可急的。同时,指针对其所指向的对象可以改变。但是我们后续会提到,世界上还有 const这么个玩意,于是指针就不能随便乱搞了。
5.其他
1)对于引用,++操作直接作用在对象上,而对指针++,大家懂得,那指针就是下一个对象的地址了(话说,指针必须有指向类型,如果是void型的指针,++操作就有问题了,它不知道步长到底是多少。)
2)由于没有空引用,一旦初始化,引用不会变成另外一个对象的引用。而指针可以变来变去,即便是const指针,假如有很多个指针指向同一个对象,假如free掉一个指针,那么其他指针就变成野指针了,这个问题值得我们注意。
3)sizeof(ref),得到的结果是引用对象的大小,而sizeof(ptr),得到的则是指针的大小,32位机上就是4个字节了。(但是,我用 double,char都可以得到这个结论,但用string却一直都是4,还得再查一下)
二:const与引用和指针
对于指针来说,const可以修饰它所指向的对象,也可以修饰指针本身。
const int* ptr 指的是ptr指向的int型对象不能被修改。
int * const ptr 指的是ptr这个指针不能指向别的对象了(也就是说,不能想指谁就指谁了。一旦限制了这个,它的作用被削弱,跟引用一样,但是还有可能产生野指针,还不如用ref呢)
const int &ref 这个说明ref所引用的对象不能被改变。我个人觉得,如果不能改变所指向的对象的值,用引用更加安全,至少不会出现野指针。速度也是一样的。
话说,对于指针来说,若const出现在*号的左边,说明是指向的对象不能改变,若const出现在*号的右边,说明指针本身不能被改变了,可以记住。
三:引用与指针的实现
引用和指针在底层的实现是一样的,其实引用虽然是别名,但是还是会占用内存空间。
参考文献:
meyer:《more effective C++》