• WAP手机版 RSS订阅 加入收藏  设为首页
教学科研

C++指针教学与研

时间:2005/10/18 8:44:41   作者:王璐   来源:王璐   阅读:5917   评论:0
内容摘要:

C++中的指针教学的实践与研究

德清学院   王璐

 

【摘要】

C++程序设计语言是现今应用较为广泛的设计语言,因其有高效和灵活的特色。而指针又是C++程序设计语言中最灵活的精华部分。初学者在很短的时间内很难掌握复杂的指针操作。虽然,现在的JAVA、C#等语言已经取消了指针,但作为一个C++程序员,指针的直接操作内存,在数据操作方面有着速度快,节约内存等优点,仍是很多C++程序员的最爱。本人在教学实践中,从简到难,探索教学中系统化的教学,使学生更全面的掌握指针的概念,提高编程能力。

 

 

【关键词】

C++     指针

 

 

指针、地址、数组及其相互关系是C++程序设计语言中最有特色的部分。通过指针可以访问到各种类型的数据。如果不能用指针编写有效正确的和灵活的程序,可以认为没有学好C++。指针概念比较复杂和抽象,使用时又很灵活。正因为这种灵活,很容易导致错误,尤其是对于初学者来说。因此在上指针这一章节时,除了教会学生指针的概念和使用方法之外,还要对指针使用中容易犯的错误和指针使用的一些小技巧做一个总结。使学生对指针有更全面的认识,能更好的使用指针编程。

(一)知识的准备

在前面的课程中已经讲授指针的概念和使用的规则,先复习概念。

实例1:

#include <iostream.h>

void main()
{

// 声明变量:

int nNumber;

int *pPointer;

// 现在给它们赋值:

nNumber = 15;

pPointer = &nNumber;

//打印出变量nNumber的值:

cout<<"nNumber is equal to :"<< nNumber<<endl;

// 现在通过指针改变nNumber的值:

*pPointer = 25;

//证明nNumber已经被上面的程序改变  

//重新打印出nNumber的值:

cout<<"nNumber is equal to :"<<nNumber<<endl;
}

请学生回答,复习指针的使用规则。画出示意图,进一步理解。

15

pPointer

nNumber

25

pPointer

nNumber

 

 

 

 

 

 

 

 


(二)陷井:指针指向了一个不存在的量

实例2:

#include <iostream.h>

int *pPointer;

void SomeFunction();

{

int nNumber;

nNumber = 25;

//让指针指向nNumber:

pPointer = &nNumber;

}

void main()

{

SomeFunction(); //pPointer赋值

//为什么这里失败了?为什么没有得到25

cout<<"Value of *pPointer: "<<*pPointer<<endl;

}

这段程序先调用了SomeFunction函数,创建了一个叫nNumber的变量,接着让指针pPointer指向了它。可是问题出在哪儿呢?当函数结束后,nNumber被删掉了,因为这是一个局部变量。局部变量在定义它的函数执行完后都会被系统自动删掉。也就是说当SomeFunction 函数返回主函数main()时,这个变量已经被删掉,但pPointer还指着变量曾经用过的但现在已不属于这个程序的区域。但这个问题怎么解决呢?答案是动态分配技术。

通过这例子还对局部变量和全局变量的概念作了复习。

(三)动态分配中的错误

态分配是指针的关键技术。它是用来在不必定义变量的情况下分配内存和让指针去指向它们。在函数返回或执行完毕时,动态分配的这块内存区域是不会被删除的。

实例3:

#include <iostream.h>

int *pPointer;

void SomeFunction()

{

//让指针指向一个新的整型

pPointer = new int;

*pPointer = 25;

}

void main()

{

SomeFunction(); // pPointer赋值

cout<<"Value of *pPointer: "<<*pPointer<<endl;

}

SomeFunction 调用时,它分配了一个内存,并让pPointer指向它。这一次,当函数返回时,新的内存区域被保留下来,所以pPointer始终指着有用的信息,这是因为了动态分配。请学生仔细阅读上面这个程序,虽然它得到了正确结果,可仍有一个严重的错误。

分配了内存,忘了回收是一个严重的错误。动态地分配了一个内存空间,可它绝不会被自动删除。也就是说,这块内存空间会一直存在,直到你告诉电脑你已经使用完了。如果你已不再需要这块内存空间了,所以它会继续占据着内存空间造成浪费,甚至你的程序运行完毕,其它程序运行时它还存在。当这样的问题积累到一定程度,最终将导致系统崩溃。所以用完动态空间以后,请释放它的空间。

正确的程序:

#include <iostream.h>

int *pPointer;

void SomeFunction()

{

// 让指针指向一个新的整型

pPointer = new int;

*pPointer = 25;

}

void main()

{

SomeFunction(); // pPointer赋值

cout<<"Value of *pPointer: "<<*pPointer<<endl;

delete pPointer;

}

请学生比较这两个程序,只有最后一行不同。如果不释放动态空间,就会制造一起“内存漏洞”,而让内存逐渐地泄漏。

(三)传递指针到函数

实例4:

请同学看下列程序是否完整。

#include <iostream.h>

void AddFive(int Number)

{

Number = Number + 5;

}

void main()

{

int nMyNumber = 18;

cout<<"My original number is "<<nMyNumber<<endl;

AddFive(nMyNumber);
cout<<"My new number is "<<nMyNumber<<endl;
//得到了结果23吗?问题出在哪儿?
}

问题出在函数AddFive里用到的Number是变量nMyNumber的一个副本而传递给函数,而不是变量本身。因此, " Number = Number + 5" 这一行是把变量的副本加了5,而原始的变量在主函数main()里依然没变。

  要解决这个问题,就要传递一个指针到函数,所以要修改一下函数让它能接受指针:把'void AddFive(int Number)' 改成 'void AddFive(int* Number)' 。下面就是改过的程序,注意函数调用时要用&号,以表示传递的是指针。

实例5:

#include <iostream.h>

void AddFive(int* Number)

{ *Number = *Number + 5;

}

void main()

{

int nMyNumber = 18;

cout<<"My original number is "<<nMyNumber<<endl;

AddFive(&nMyNumber);

cout<<"My new number is "<<nMyNumber<<endl;

}

(四)指向类的指针

这部分内容可放在内这一章中补充介绍。

指针在类中的操作要格外小心。

¨         定义一个类:

class MyClass

{

public:

  int m_Number;

  char m_Character;

};

¨         定义一个MyClass 类的变量:

MyClass thing;

¨         定义一个指针:

MyClass *thing;

¨         分配个内存空间

thing = new MyClass;

注意,问题出现了。通常使用指针时可能会写'thing.m_Number',但是thing是类吗,不,它是一个指向类的指针,它本身并不包含一个叫m_Number的变量。所以我们必须用另一种方法:就是把'.'(点号)换成 -> ,来看下面的例子:

实例6:

#include <iostream.h>

class MyClass

{

public:

int m_Number;

char m_Character;

};

void main()

{

MyClass *pPointer;

pPointer = new MyClass;

pPointer->m_Number = 10;

pPointer->m_Character = 's';

delete pPointer;

}

(五)指向数组的指针

指针指向一个数组,按下面的方法操作:

int *pArray;

pArray = new int[6];

程序会创建一个指针pArray,让它指向一个有六个元素的数组。另外一种方法,不用动态分配:

实例7:

int *pArray;

int MyArray[6];

pArray = &MyArray[0];

注意,&MyArray[0] 也可以简写成 MyArray ,都表示是数组的第一个元素地址。但如果写成pArray = &MyArray可能就会出问题,结果是 pArray 指向的是指向数组的指针(在一维数组中尽管与&MyArray[0]相等),在多维数组中很容易出错。

(六)在数组中使用指针:

一个指向整型数组的指针:

实例8:

#include <iostream.h>

void main()

{

int Array[3];

Array[0] = 10;

Array[1] = 20;

Array[2] = 30;

int *pArray;

pArray = &Array[0];

cout<<"pArray points to the value %d\n";

cout<<*pArray<<endl;

}

如果让指针指向数组元素中的下一个,可以用pArray++.也可以用你应该能想到的pArray + 1,都会让指针指向数组的下一个元素。要注意的是你在移动指针时,程序并不检查你是否已经移动地超出了你定义的数组,也就是说你很可能通过上面的简单指针加操作而访问到数组以外的数据,而结果就是,可能会使系统崩溃,所以请格外小心。如:

实例9:

#include <iostream.h>

void SomeFunction(int * pArray)

{   for(int j<0;j<9;j++)

    cout<<*(pArray+j);

    cout<<endl;

}

void main( )

{    int Array[3]={10,20,30};

     SomeFunction(Array);

}

当然有了pArray + 1,也可以有pArray - 1,这种操作在循环中很常用,特别是while循环中。

另一个需要注意的是,如果你定义了一个指向整型数的指针:int* pNumberSet ,你可以把它当作是数组,如:pNumberSet[0] 和 *pNumberSet是相等的,pNumberSet[1]与*(pNumberSet + 1)也是相等的。

实例10:

#include <iostream.h>

void main()

{

int Array[3];

Array[0] = 10;

Array[1] = 20;

Array[2] = 30;

int *pArray;

pArray = &Array[0];

cout<<"pArray points to the value %d\n";

cout<<*pArray<< pArray[0]<< endl;

cout<<*(pArray+1)<<pArray[1]<<endl;

cout<<Array[0]<<*Array;

cout<<Array[1]<<*(Array+1);

}

除了以上对指针相关知识的总结,还可以设计一些同步的上机练习,让学生自己做一做,加深对指针的理解;煅炼学生的编程能力,为日后独立的完成毕业作业打下基础。更重要的是通过这种形式的学习,培养学生总结、归纳知识的习惯和能力。

 

C++写的代码均在VC++中编译通过。

 

参考书目

[1]李宁  C++语言程序设计   北京:中央广播电视大学

[2]Kris Jamsa著,魏津等译C/C++使用技巧1001例   北京:电子工业出版社

[3]C语言程序设计基础   上海:复量大学出版社


浙ICP备10016676号