[TOC]点开本文的朋友,如果你没有“指针”的概念,请面壁思索。你不是正统的程序员,你是野路子,faker,注定你在技术的道路上走不远。闲话少说,正文开始。1、从运算符开始,我们要看“引用”和“指针”的区别,首先要看运算符。在c/c++中,与指针相关的运算符有3种:&->*在Java中,与引用相关的运算符有1种:。什么,引用只有一种运算符???那我们就来看看每个算子是干什么的。注:指针以结构体为例,方便与引用对象进行比较1.1.C/C++中指针运算符&->*的作用定义一个结构体和变量typedefstuct{intsex;intage;}student_t;student_tstu1={1,20};运算符&,将数据的地址读入指针:int*p_addr=&stu1;//创建一个指针p_addr,p_addrstoragestu1的地址运算符->用于读写指针指向的结构体的成员数据intage=p_addr->age;p_addr->age=44;运算符*读取/写入指针中的地址数据:student_tstu2=*p_addr;//读取p_addr地址的数据到stu2*p_addr={2,8};//将数据写入p_addr地址注:c++中也有引用,但不在本文讨论范围内1.2,Java中引用运算符的使用。定义一个类和对象publicclassStudent{publicIntegersex;公共整数年龄;学生(整数s,整数a){性别=s;年龄=一个;}}学生stu1=新学生(1,20);//创建stu1的引用,stu1中存放的数据不是对象的数据,而是对象的地址,即引用//stu1存放在栈中,而对象存放在堆中将数据的地址读入ReferenceStudentp_addr=stu1;//创建p_addr的引用,将stu1中存储的对象的地址赋值给p_addr来读写该对象地址的成员数据的引用Integerage=stu.age;stu.age=44;注意:Java只有引用,没有指针,引用弱化了地址和数据的关系。概念,所以程序员必须更深刻地理解引用的本质,写出更健壮的代码。从这一点来看,C/C++指针的运算符*可以做到Java引用做不到的事情,即指针可以直接引用地址。数据是读/写的,引用不是。那我们来看看,具体的工作是指针可以做,引用做不到。..2.指针可以做引用做不到的事~2.1.指针可以指向任何地址,而引用只能指向一个对象。指针可以使用运算符&给数据的地址,也可以直接给指针一个地址,甚至空地址student_t*p_addr=&stu1;student_t*p_addr=0x12000;student_t*p_addr=NULL;指针可以通过地址加减来修改相邻地址的数据,比如修改一个数组intdata[4]={1,2,3,4};int*p_addr=data;*p_addr=6;p_addr+=1;*p_addr=7;p_addr+=1;*p_addr=8;p_addr+=1;*p_addr=9;//这个数组中的数据是:{6,7,8,9}引用只能指向一个对象,不能直接赋地址,也不能为空。学生stu=newStudent();学生stu=0x12000;//抱歉,编译失败。..2.1.1.有什么用?在开发底层驱动时,寄存器的地址是固定的。如果要修改寄存器中的数据,需要创建一个指针,将寄存器的地址赋值给指针,然后修改寄存器。//点亮LEDint*p_led_addr=0x1233;//LED寄存器地址为0x1233,赋值给指针p_led_addr*p_led_addr=1;//LED打开*p_led_addr=0;//LED关闭intstate=*p_led_addr;//读取LED的亮灭状态,修改连续地址的多个寄存器//点亮多个LEDsint*p_led_addr=0x1233;//LED寄存器地址为0x1233,赋值给指针p_led_addr*p_led_addr=1;//LED亮起*(p_led_addr+1)=1;//LED2打开*(p_led_addr+2)=1;//很明显LED3亮了,可以做参考吗???做不到!2.2.指针可以自由修改指向地址的数据指针大法student_t*p_addr=&stu1;//创建一个Student类型的指针,指向一个stu1*p_addr=24242;//将24242写入stu1的地址引用只能修改指向对象的固定成员有什么用,或者通过指向对象提供的固定方法修改数据?好像没用。..3、指针的缺陷3.1.野指针的定义指针在创建时并没有初始化,指向的地址是随机的!这时指针读写,破坏程序运行!指针指向的地址处的数据已被释放。如果此时读取或写入指针,程序运行就会被破坏!原因是指针可以指向任何地址;而引用必须指向某个对象。指针不能自动去指向;当指向的对象被销毁时,引用将自动取消引用。结果导致程序崩溃,无法正常运行。代码漏洞3.2、C语言强制类型转换导致的内存错误修改定义了将A类型的变量s强制转换为B类型,然后将s的地址赋值给指向B类型的指针p,数据此时B类型的结构体是对指针p进行读写操作,可能与A类型不兼容,导致变量s被错误修改。原因是C语言强制类型转换没有严格检查,太粗鲁了。这就是C++引入四个转换字符的原因。后果是程序崩溃,无法按预期运行。漏洞4.总结4.1.引用能做到的,指针能做到,没有损失——反之,指针运算符*就做不到。能用引用做的事不能用引用做,即指针可以直接读写该地址的数据。参考不能。指针可以指向任何地址(甚至是空地址),而引用只能指向一个对象(非空引用)。指针可以加减地址来修改相邻地址处的数据。比如修改一个数组指针不能自动Unpointing;当指向的对象被销毁时,引用将自动取消引用。指针可以随意修改指向地址处的数据。指针的灵活性带来了缺陷,引用的不灵活带来了安全引用,避免了地址的直接读写,增强了内存操作的规范,从而增强了语言内存安全性,降低了对开发者的要求。指针和引用各有各的用途。了解了本质之后,我们就可以在不同的场景下选择合适的工具了!4.3.题外话:C++引用和Java引用的区别。在C++中,引用指向的地址是不会变的,变的是指向地址的内容,而Java中引用指向的地址是在变的!!如果非要比较的话,那么Java中的“引用”更类似于C/C++的指针,与C++的“引用”有很大区别。Java去掉了指针的概念,直接用引用...你看java:Aa=newA(1);Ab=新A(2);b=一个;没问题,a和b引用了同一个对象A(2),原来的A(1)变成了未引用对象。垃圾收集机制将在稍后的某个时间杀死A(1)。但C++不是。C++引用在语义上是“别名”[本质上是一个const指针,也称为指针常量],而不是指针的另一种用法:Aa=A(1);Ab=A(2);A&c=b;//c是b的别名c=a;//不是c引用a,而是一个拷贝操作但是C++的引用机制非常纯粹,它只是一个别名,一旦定义就不能修改,即不能指向其他变量。每种语言的特质都是整体的一个组成部分。我们知道java的引用机制是一个非常复杂的机制。他必须区分“基本对象”和“复合对象”。大家可以想象一下,如果没有基础对象,我们如何完成对象的复制呢?唯一的解决办法就是提供两个等号,或者全部使用构造函数……但总的来说,他和垃圾回收形成了一个相当完美的组合。C++引用机制为运算符重载提供了实质性支持。C++的引用从根本上要求用类“模拟”原始对象。如果C++像Java一样使用引用,那么原本漂亮的operator[]、代理类等就很难实现了。此外,C++的运算符重载为C++的模板机制提供了强大的支持
