文档章节

从Java到C++——指针与引用

自由的角马
 自由的角马
发布于 2015/01/10 13:57
字数 1623
阅读 10
收藏 0

JavaC++——指针与引用

C++即有指针又有引用,而且很多时候具有相似的功能,常常容易让人混淆,着实让人头痛。用两句通俗的话说明两者本质的含意:引用就是一个变量或对象的别名(引用的本质是一个对象);指针是一个段内存空间的地址(指向存储一个变量值的空间或一个对象的空间);如下图所示:

 
 

 

C++中的引用与指针

引用

引用是为变量或对象起的另外一个别名,定义形式:T& v;  T为类型,v为变量名。使用引用时,注意以下几点:

1.引用在创建的时候必须被初始化(指针可以在任何时候赋值)

2.一旦引用初始化后,就不能改变引用所指向的变量(或对象),一直和该变量(或对象)邦定在一起

3.引用必须与一个确定的合法内存单元相关联。不存在NULL引用。(指针可以为NULL)

下面用例子来解释,【例1】:

void Reference()

{

//int &r1; //不符第1要点, 报错  Error:refercece value "r" requires an intializer

//int & r2 = 100; //非const类型的引用,不能与常量邦定在一起

int i = 10;

int &r3 = i; //引用r2与变量i邦定在一起,符合第1要点

cout << "初始值  i:" << i << "   r3:"  << r3 << endl;

i = 15; //改变i的值,r3跟着改变,因为i和r3是指向同一块内存,符合第2要点

cout << "改变i   i:" << i << "   r3:"  << r3 << endl;

r3 = 20; //改变r3的值,i跟着改变,因为i和r3是指向同一块内存是,符合第2要点

cout << "改变r3  i:" << i << "   r3:"  << r3 << endl;

int i2 = 25;

r3 = i2; //并不是引用r3指向了变量i2,而是i2的值赋给了变量i(r3所指向的变量),符合第2要点

cout << "赋值r3  i:" << i << "   r3:"  << r3 << "   i2:" << i2 << endl;

int& r4 = r3; //用引用r3指向的变量i的值初始化引用r4,所用r3,r4邦定的是同一个变量i;r3、r4、i指向同一块内存

cout << "引用r4  i:" << i << "   r3:"  << r3 << "   r4:" << r4 << endl;

Data d;

Data& rData = d; //也可对对象进行引用,原理与变量一样。

cout << "d.iVal:" << d.iVal << "   rData.iVal:" << rData.iVal << endl;

d.iVal = 8;

cout << "d.iVal:" << d.iVal << "   rData.iVal:" << rData.iVal << endl;

}

结果:

初始值  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

void TestPointer()

{

double* p1; //定义一个指向double类型的指针p1,指针未被初始化,可能指向任意一个地址

double dVal1 = 2; 

p1 = &dVal1; //给指针p1赋值, &是取地址符,也就是把dVal1的地址赋给p1

cout << "p1:" << p1 << "   *p1:" << *p1 << endl; //*是解引用符,*p1也就是获取指针p1所指向的变量dVal1的值

double* p2 = p1; //定义指针p2,同时将p1的值赋给p2,这时p1和p2指向同一个地址

cout << "p1:" << p1 << "   p2:" << p2 << "   *p1:" << *p1 << "   *p2:" << *p2 << endl;

}

结果:

p1:001AF6B8

*p1:2

p1:001AF6A8   p2:001AF6A8   *p1:5   *p2:5

 

我们也可以用debug模式对它进行调试,这样可以看到各个变量的内存地址,如下:

 
 

 

指针的值的状态

指针的值(即地址)应是下面四种状态之一:

1.指向一个对象(或内置类型变量)

2.指向紧邻对象所占空间的下一个位置;

3.空指针,意味着没有指向任何对象;

4.无效指针,也就是以上情况之外的其它值。

举例解释【例3

void TestPointer2()

{

short sInt = 65;

short *sP; //状态4,未被初始化,无效指针

//cout << sP << endl; //错误,将报异常:The variable 'sP' is being used without being initialized.

sP = &sInt; //状态1,指向变量ch

cout << "cP:" << sP << "  *cP:" << *sP << endl;

sP ++; //状态2,指向变量sInt所在地址的下一个地址

cout << "cP:" << sP << endl;

sP = NULL; //状态3,空指针

cout << "cP:" << sP << endl;

}

结果:

cP:0037FD54  *cP:65

cP:0037FD56

cP:00000000

 

 

易错点

对于初学者或是从其它语言转向c++的人来说,指针和引用这部分比较难,我觉得主要有以下几点,也是大家需要注意的:

 

1.&符号的多意性(多个用途)

&即用在引用也用在指针。定义引用变量,一般在“=”的左侧,在类型后加&符号(如果是在一行内定义多个引用,则每个变量名前加&)表示取变量地址,一般在“=”的右侧用于给指针赋值,&在变量名前面。

void TestSymbol()

{

int nVal1 = 5;

int nVal2 = 6;

int nVal3 = 9;

int& rVal1 = nVal1; //定义引用

int &rVal2 = nVal2, &rVal3 = nVal3; //定义引用

cout << "rVal1:" << rVal1 << "  rVal2:" << rVal2 << "  rVal3:" << rVal3 << endl;

 

int *p1, *p2, *p3;

p1 = &nVal1; //取nVal1的地址,给p1赋值

p2 = &nVal2, p3 = &nVal3; //取nVal2, nVal3地址,分别给p2、p3赋值

cout << "*p1:" << *p1 << "  *p2:" << *p2 << "  *p3:" << *p3 << endl;

}

 

2.引用和指针的定义

一行内定义多个引用,每个引用前都要加&;一行内定义多个指针,每个引用前都要加*。引用的类型要和它所邦定的变量或对象匹配;指针的类型要和它所指向的变量或对象匹配。

void ReferencePointer()

{

int nVal1 = 10;

int nVal2 = 20;

int &rVal1 = nVal1, &rVal2 = nVal2;

cout << "rVal1:" << rVal1 << "  rVal2:" << rVal2 << endl;

int *p1 = &nVal1, *p2 = &nVal2, *p3 = &nVal2; //p2和p3指向同一个地址

cout << "*p1:" << *p1 << "    *p2:" << *p2 << endl;

double dVal = 10.125;

//double& rDVal = nVal1; //类型不匹配,编译错误

//double *p = &nVal1; //类型不匹配,编译错误

}

结果:

rVal1:10  rVal2:20

*p1:10    *p2:20


本文转载自:http://blog.csdn.net/luoweifu/article/details/38308299

自由的角马
粉丝 1
博文 269
码字总数 0
作品 0
文山
私信 提问
Android JNI(一)——NDK与JNI基础

本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Native相互调用 Android JNI学习(四)——JNI的常用方法...

隔壁老李头
2018/05/09
0
0
android开发教程(3)— jni编程之采用SWIG从Java调用C/C++

Android 从Java调用C/C++ 当无法用 Java 语言编写整个应用程序时,JNI 允许您调用C/C++本机代码。在下列典型情况下,您可能决定使用本机代码: 希望用更低级、更快的编程语言C/C++去实现对时...

刘小米_思聪
2014/09/16
4.7K
0
Java中的引用和C++中引用的区别

用过java和C++的同学都知道在二者中均有引用的概念。但是这两个概念所代表的并不相同。 首先了解C++ 中引用的含义:“引用”即“别名”。C++中的引用代表的就是实际的存储空间。对其进行操作...

osDaniel
2013/12/02
999
0
本地方法怎么映射Java层的数据类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wangyangzhizhou/article/details/79576578 前言 Java 语言上定义了不同的数据类型,比如有基础类型、等等,还...

超人汪小建(seaboat)
2018/03/16
0
0
浅析:Java与C++的主要区别

Java区别于C++ 表面看来两者最大的不同在于Java没有指针,或者说,Java满地都是指针。对于编程者而言Java的这种设计是安全且更易用的。说Java满地是指针的原因在于它把指针的功能隐藏了,其实...

Ace☞Tseng
2012/10/09
317
0

没有更多内容

加载失败,请刷新页面

加载更多

c语言实现Sqlite3的创建db和增删改查db操作

SQLite,是一款轻型的数据库,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中使用广泛,现在准备学习一下sqlite3的使用方法并写一个测试demo,后面在项目智能...

jorin_zou
23分钟前
4
0
【2019年8月版本】OCP 071认证考试最新版本的考试原题-第2题

choose three Which three are true about the CREATE TABLE command? A) It can include the CREATE...INDEX statement for creating an index to enforce the primary key constraint. B) ......

oschina_5359
26分钟前
5
0
如何在二维码中循环批量插入图片

现在二维码种类比较多,为了突出二维码的个性及吸引客户,很多朋友都喜欢在二维码上插入图片。想要每个二维码都与众不同,但是有的时候需要批量插入图片数量有限,如果制作的二维码比较多的话...

中琅软件
27分钟前
6
0
LTR那点事—AUC及其与线上点击率的关联详解

LTR(Learning To Rank)学习排序是一种监督学习(SupervisedLearning)的排序方法,现已经广泛应用于信息索引,内容推荐,自然语言处理等多个领域。以推荐系统为例,推荐一般使用多个子策略...

达观数据
27分钟前
5
0
IntelliJ 如何显示代码的代码 docs

希望能够在 IntelliJ 代码上面显示方法的 docs。 如何进行显示? 你可以使用 Ctrl + Q 这个快捷键来查看方法的 Docs。 https://blog.ossez.com/archives/3061...

honeymoose
30分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部