C++指针基础入门.doc_第1页
C++指针基础入门.doc_第2页
C++指针基础入门.doc_第3页
C++指针基础入门.doc_第4页
C++指针基础入门.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C+指针基础入门 什么是指针? 其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实的数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据。这是一个非常重要的概念,有很多程序和算法都是围绕指针而设计的,如链表。 开始学习 如何定义一个指针呢?就像你定义一个其它变量一样,只不过你要在指针名字前加上一个星号。我们来看一个例子:下面这个程序定义了两个指针,它们都是指向整型数据。int*pNumberOne;int*pNumberTwo; 你注意到在两个变量名前的“p”前缀了吗?这是程序员通常在定义指针时的一个习惯,以提高便程序的阅读性,表示这是个指针。现在让我们来初始化这两个指针:pNumberOne=&some_number;pNumberTwo=&some_other_number; &号读作“什么的地址”,它表示返回的是变量在内存中的地址而不是变量本身的值。在这个例子中,pNumberOne 等于some_number的地址,所以现在pNumberOne指向some_number. 如果现在我们在程序中要用到some_number,我们就可以使用pNumberOne. 我们来学习一个例子:在这个例子中你将学到很多,如果你对指针的概念一点都不了解,我建议你多看几遍这个例子,指针是个很复杂的东西,但你会很快掌握它的。 这个例子用以增强你对上面所介绍内容的了解。它是用C编写的(注:原英文版是用C写的代码,译者重新用C+改写写了所有代码,并在DEV C+ 和VC+中编译通过!)#include void main()/ 声明变量:int nNumber;int *pPointer;/ 现在给它们赋值:nNumber = 15;pPointer = &nNumber;/打印出变量nNumber的值:coutnNumber is equal to : nNumberendl;/ 现在通过指针改变nNumber的值:*pPointer = 25;/证明nNumber已经被上面的程序改变/重新打印出nNumber的值: coutnNumber is equal to :nNumberendl; 通读一下这个程序,编译并运行它,务必明白它是怎样工作的。如果你完成了,准备好,开始下一小节。 陷井! 试一下,你能找出下面这段程序的错误吗?#includeint*pPointer;voidSomeFunction();intnNumber;nNumber=25;/让指针指向nNumber:pPointer=&nNumber;voidmain()SomeFunction();/为pPointer赋值/为什么这里失败了?为什么没有得到25coutValueof*pPointer:*pPointerendl; 这段程序先调用了SomeFunction函数,创建了个叫nNumber的变量,接着让指针pPointer指向了它。可是问题出在哪儿呢?当函数结束后,nNumber被删掉了,因为这一个局部变量。局部变量在定义它的函数执行完后都会被系统自动删掉。也就是说当SomeFunction 函数返回主函数main()时,这个变量已经被删掉,但pPointer还指着变量曾经用过的但现在已不属于这个程序的区域。如果你还不明白,你可以再读读这个程序,注意它的局部变量和全局变量,这些概念都非常重要。 但这个问题怎么解决呢?答案是动态分配技术。注意这在C和C+中是不同的。由于大多数程序员都是用C+,所以我用到的是C+中常用的称谓。 动态分配 动态分配是指针的关键技术。它是用来在不必定义变量的情况下分配内存和让指针去指向它们。尽管这么说可能会让你迷惑,其实它真的很简单。下面的代码就是一个为一个整型数据分配内存的例子:int*pNumber;pNumber=newint; 第一行声明一个指针pNumber.第二行为一个整型数据分配一个内存空间,并让pNumber指向这个新内存空间。下面是一个新例,这一次是用double双精型:double*pDouble;pDouble=newdouble; 这种格式是一个规则,这样写你是不会错的。 但动态分配又和前面的例子有什么不同呢?就是在函数返回或执行完毕时,你分配的这块内存区域是不会被删除的所以我们现在可以用动态分配重写上面的程序:#includeint*pPointer;voidSomeFunction()/让指针指向一个新的整型pPointer=newint;*pPointer=25;voidmain()SomeFunction();/为pPointer赋值coutValueof*pPointer:*pPointerendl; 通读这个程序,编译并运行它,务必理解它是怎样工作的。当SomeFunction 调用时,它分配了一个内存,并让pPointer指向它。这一次,当函数返回时,新的内存区域被保留下来,所以pPointer始终指着有用的信息,这是因为了动态分配。但是你再仔细读读上面这个程序,虽然它得到了正确结果,可仍有一个严重的错误。 分配了内存,别忘了回收太复杂了,怎么会还有严重的错误!其实要改正并不难。问题是:你动态地分配了一个内存空间,可它绝不会被自动删除。也就是说,这块内存空间会一直存在,直到你告诉电脑你已经使用完了。可结果是,你并没有告诉电脑你已不再需要这块内存空间了,所以它会继续占据着内存空间造成浪费,甚至你的程序运行完毕,其它程序运行时它还存在。当这样的问题积累到一定程度,最终将导致系统崩溃。所以这是很重要的,在你用完它以后,请释放它的空间,如:delete pPointer;这样就差不多了,你不得不小心。在这你终止了一个有效的指针(一个确实指向某个内存的指针)。 下面的程序,它不会浪费任何的内存:#includeint*pPointer;voidSomeFunction()/让指针指向一个新的整型pPointer=newint;*pPointer=25;voidmain()SomeFunction();/为pPointer赋值coutValueof*pPointer:*pPointerendl;deletepPointer; 只有一行与前一个程序不同,但就是这最后一行十分地重要。如果你不删除它,你就会制造一起“内存漏洞”,而让内存逐渐地泄漏。 (译者:假如在程序中调用了两次SomeFunction,你又该如何修改这个程序呢?请读者自己思考) 传递指针到函数传递指针到函数是非常有用的,也很容易掌握。如果我们写一个程序,让一个数加上5,看一看这个程序完整吗?:#includevoidAddFive(intNumber)Number=Number+5;voidmain()intnMyNumber=18;coutMyoriginalnumberisnMyNumberendl;AddFive(nMyNumber);coutMynewnumberisnMyNumberendl;/得到了结果23吗?问题出在哪儿? 问题出在函数AddFive里用到的Number是变量nMyNumber的一个副本而传递给函数,而不是变量本身。因此, Number = Number + 5 这一行是把变量的副本加了5,而原始的变量在主函数main()里依然没变。试着运行这个程序,自己去体会一下。 要解决这个问题,我们就要传递一个指针到函数,所以我们要修改一下函数让它能接受指针:把void AddFive(int Number) 改成 void AddFive(int* Number)。下面就是改过的程序,注意函数调用时要用号,以表示传递的是指针:#includevoidAddFive(int*Number)*Number=*Number+5;voidmain()intnMyNumber=18;coutMyoriginalnumberisnMyNumberendl;AddFive(&nMyNumber);coutMynewnumberisnMyNumber ,来看下面的例子:classMyClasspublic:intm_Number;charm_Character;voidmain()MyClass*pPointer;pPointer=newMyClass;pPointer-m_Number=10;pPointer-m_Character=s;deletepPointer; 指向数组的指针 你也可以让指针指向一个数组,按下面的方法操作:int*pArray;pArray=newint6; 程序会创建一个指针pArray,让它指向一个有六个元素的数组。另外一种方法,不用动态分配:int*pArray;intMyArray6;pArray=&MyArray0; 注意,&MyArray0 也可以简写成 MyArray ,都表示是数组的第一个元素地址。但如果写成pArray = &MyArray可能就会出问题,结果是 pArray 指向的是指向数组的指针(在一维数组中尽管与&MyArray0相等),而不是你想要的,在多维数组中很容易出错。 在数组中使用指针 一旦你定义了一个指向数组的指针,你该怎样使用它呢?让我们来看一个例子,一个指向整型数组的指针:#includevoidmain()intArray3;Array0=10;Array1=20;Array2=30;int*pArray;pArray=&Array0;coutpArraypointstothevalue%dn*pArrayendl; 如果让指针指向数组元素中的下一个,可以用pArray+.也可以用你应该能想到的pArray + 1,都会让指针指向数组的下一个元素。要注意的是你在移动指针时,程序并不检查你是否已经移动地超出了你定义的数组,也就是说你很可能通过上面的简单指针加操作而访问到数组以外的数据,而结果就是,可能会使系统崩溃,所以请格外小心。 当然有了pArray + 1,也可以有pArray 1,这种操作在循环中很常用,特别是while循环中。 另一个需要注意的是,如果你定义了一个指向整型数的指针:int* pNumberSet ,你可以把它当作是数组,如:pNumberSet0 和 *pNumberSet是相等的,pNumberSet1与*(pNumberSet + 1)也是相等的。 在这一节的最后提一个警告:如果你用 new 动态地分配了一个数组,int*pArray;pArray=newint6; 别忘了回收,deletepArray; 这一句是告诉编译器是删除整个数组而不一个单独的元素。千万记住了。 后话 这一句是告诉编译器是删除整个数组而不一个单独的元素。千万记住了。还有一点要小心,别删除一个根本就没分配内存的指针,典型的是如果没用new分配,就别用delete:voidmain()intnumber;int*pNumber=number;deletepNumber;/错误-*pNumber没有用new动态分配内存. 常见问题解答Q:为什么我在编译程序时老是在 new 和 delete语句中出现symbol undefined 错误? A:new 和 delete都是C+在C上的扩展,这个错误是说编译器认为你现在的程序是C而不C+,当然会出错了。看看你的文件名是不是。cpp结尾。 Q:new 和 malloc有什么不同? A:new 是C+中的关健字,用来分配内存的一个标准函数。如果没有必要,请不要在C+中使用malloc.因为malloc是C中的语法,它不是为面向对象的C+而设计的。 Q:我可以同时使用free 和 delete吗? A:你应该注意的是,它们各自所匹配的操作不同。free只用在用malloc分配的内存操作中,而delete只用在用new分配的内存操作中。 引用(写给某些有能力的读者) 这一节的内容不是我的这篇文章的中心,只是供某些有能力的读者参考。 有些读者经常问我关于引用和指针的问题,这里我简要地讨论一下。 在前面指针的学习中,我们知道()是读作“什么的地址”,但在下面的程序中,它是读作“什么的引用”int&Number=myOtherNumber;Number=25; 引用有点像是一个指向myOtherNumber的指针,不同的是它是自动删除的。所以他比指针在某些场合更有用。与上面等价的代码是:int*pNumber=&myOtherNumber;*pNumber=25; 指针与引用另一个不同是你不能修改你已经定义好的引用,也就是说你不能改变它在声明时所指的内容。举个例子:int myFirstNumber = 25;int mySecondNumber = 20;int &myReference = myFirstNumber;myReference = mySecondNumber;/这一步能使myReference 改变吗?coutmyFristNumberendl;/结果是20还是25?当在类中操作时,引用的值必须在构造函数中设定,例:CMyClass:CMyClass(int &variable) : m_MyReferenceInCMyClass(variable)/ constructor code here 总结 这篇文章开始可能会较难掌握,所以最好是多读几遍。有些读者暂时还不能理解,在这儿我再做一个简要的总结:指针是一个指向内存区域的变量,定义时在变量名前加上星号(*)(如:int *number)。 你可以得到任何一个变量的地址,只在变量名前加上(如:pNumber = &m

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论