从Java到C++——指针与引用
C++即有指针又有引用,而且很多时候具有相似的功能,常常容易让人混淆,着实让人头痛。用两句通俗的话说明两者本质的含意:引用就是一个变量或对象的别名(引用的本质是一个对象);指针是一个段内存空间的地址(指向存储一个变量值的空间或一个对象的空间);如下图所示:
C++中的引用与指针
引用
引用是为变量或对象起的另外一个别名,定义形式:T& v;T为类型,v为变量名。使用引用时,注意以下几点:
1.引用在创建的时候必须被初始化(指针可以在任何时候赋值)
2.一旦引用初始化后,就不能改变引用所指向的变量(或对象),一直和该变量(或对象)邦定在一起。
3.引用必须与一个确定的合法内存单元相关联。不存在NULL引用。(指针可以为NULL)
下面用例子来解释,【例1】:voidReference()
{
//int &r1;//不符第1要点, 报错 Error:refercece value "r" requires an intializer
//int & r2 = 100;//非const类型的引用,不能与常量邦定在一起
inti = 10;
int&r3 = i;//引用r2与变量i邦定在一起,符合第1要点
cout <
i = 15;//改变i的值,r3跟着改变,因为i和r3是指向同一块内存,符合第2要点
cout <
r3 = 20;//改变r3的值,i跟着改变,因为i和r3是指向同一块内存是,符合第2要点
cout <
inti2 = 25;
r3 = i2;//并不是引用r3指向了变量i2,而是i2的值赋给了变量i(r3所指向的变量),符合第2要点
cout <
int& r4 = r3;//用引用r3指向的变量i的值初始化引用r4,所用r3,r4邦定的是同一个变量i;r3、r4、i指向同一块内存
cout <
Data d;
Data& rData = d;//也可对对象进行引用,原理与变量一样。
cout <
d.iVal = 8;
cout <
}
结果:
初始值 i:10 r3:10
改变i i:15 r3:15
改变r3 i:20 r3:20
赋值r3 i:25 r3:25 i2:25
引用r4 i:25 r3:25 r4:25
d.iVal:0 rData.iVal:0
d.iVal:8 rData.iVal:8
我们也可以用debug模式对它进行调试,这样可以看到各个变量的内存地址,如下:
指针
指针是指向另外一个类型的复合类型,定义形式:T* p;T为类型,p为指针变量。与引用类似,指针也实现了其它变量或对象的间接访问。使用指针变量p时,在p的前面加上*(即:*p)就是解引用符,用来访问指针所指向的对象。指针具有以下特点:
1.指针本身就是一个对象,允许对指针进行赋值和拷贝;
2.指针的生命周期内它可以先后指向几个不同的对象;
3.指针无须在定义时赋初值;
4.与内置类型一样,如果指针没有初始化,将指向一个不确定的值;
5.不能定义指向引用的指针(因为引用不是对象,没有实际的地址)。
【例2】voidTestPointer()
{
double* p1;//定义一个指向double类型的指针p1,指针未被初始化,可能指向任意一个地址
doubledVal1 = 2;
p1 = &dVal1;//给指针p1赋值, &是取地址符,也就是把dVal1的地址赋给p1
cout <
double* p2 = p1;//定义指针p2,同时将p1的值赋给p2,这时p1和p2指向同一个地址
cout <
}
结果:
p1:001AF6B8
*p1:2
p1:001AF6A8 p2:001AF6A8 *p1:5 *p2:5
我们也可以用debug模式对它进行调试,这样可以看到各个变量的内存地址,如下:
指针的值的状态
指针的值(即地址)应是下面四种状态之一:
1.指向一个对象(或内置类型变量);
2.指向紧邻对象所占空间的下一个位置;
3.空指针,意味着没有指向任何对象;
4.无效指针,也就是以上情况之外的其它值。
举例解释【例3】voidTestPointer2()
{
shortsInt = 65;
short*sP;//状态4,未被初始化,无效指针
//cout <
sP = &sInt;//状态1,指向变量ch
cout <
sP ++;//状态2,指向变量sInt所在地址的下一个地址
cout <
sP = NULL;//状态3,空指针
cout <
}
结果:
cP:0037FD54 *cP:65
cP:0037FD56
cP:00000000
易错点
对于初学者或是从其它语言转向c++的人来说,指针和引用这部分比较难,我觉得主要有以下几点,也是大家需要注意的:
1.&符号的多意性(多个用途)
&即用在引用也用在指针。定义引用变量,一般在“=”的左侧,在类型后加&符号(如果是在一行内定义多个引用,则每个变量名前加&);表示取变量地址,一般在“=”的右侧用于给指针赋值,&在变量名前面。voidTestSymbol()
{
intnVal1 = 5;
intnVal2 = 6;
intnVal3 = 9;
int& rVal1 = nVal1;//定义引用
int&rVal2 = nVal2, &rVal3 = nVal3;//定义引用
cout <
int*p1, *p2, *p3;
p1 = &nVal1;//取nVal1的地址,给p1赋值
p2 = &nVal2, p3 = &nVal3;//取nVal2, nVal3地址,分别给p2、p3赋值
cout <
}
2.引用和指针的定义
一行内定义多个引用,每个引用前都要加&;一行内定义多个指针,每个引用前都要加*。引用的类型要和它所邦定的变量或对象匹配;指针的类型要和它所指向的变量或对象匹配。voidReferencePointer()
{
intnVal1 = 10;
intnVal2 = 20;
int&rVal1 = nVal1, &rVal2 = nVal2;
cout <
int*p1 = &nVal1, *p2 = &nVal2, *p3 = &nVal2;//p2和p3指向同一个地址
cout <
doubledVal = 10.125;
//double& rDVal = nVal1;//类型不匹配,编译错误
//double *p = &nVal1;//类型不匹配,编译错误
}
结果:
rVal1:10 rVal2:20
*p1:10 *p2:20
原文:http://blog.csdn.net/luoweifu/article/details/38308299