科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件关于指针入门的最好的文章

关于指针入门的最好的文章

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

作为一个C++程序员,指针的直接操作内存,在数据操作方面有着速度快,节约内存等优点,仍是很多C++程序员的最爱。

作者:51cto.com整理 来源:51cto.com 2007年9月15日

关键字: 指针 入门 软件

  • 评论
  • 分享微博
  • 分享邮件
什么是指针?

其实指针就像是其它变量一样,所不同的是一般的变量包含的是实际的真实
的数据,而指针是一个指示器,它告诉程序在内存的哪块区域可以找到数据。这
是一个非常重要的概念,有很多程序和算法都是围绕指针而设计的,如链表。


开始学习

如何定义一个指针呢?就像你定义一个其它变量一样,只不过你要在指针名
字前加上一个星号。我们来看一个例子:
下面这个程序定义了两个指针,它们都是指向整型数据。


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 <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;
}

通读一下这个程序,编译并运行它,务必明白它是怎样工作的。如果你完成
了,准备好,开始下一小节。


陷井!

试一下,你能找出下面这段程序的错误吗?

#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还指着变量曾经用过的但现在已不属于这个程序的区域。如果你还不明
白,你可以再读读这个程序,注意它的局部变量和全局变量,这些概念都非常重
要。
但这个问题怎么解决呢?答案是动态分配技术。注意这在C和C++中是不同
的。由于大多数程序员都是用C++,所以我用到的是C++中常用的称谓。



动态分配

动态分配是指针的关键技术。它是用来在不必定义变量的情况下分配内存和
让指针去指向它们。尽管这么说可能会让你迷惑,其实它真的很简单。下面的代
码就是一个为一个整型数据分配内存的例子:
int *pNumber;
pNumber = new int;
第一行声明一个指针pNumber。第二行为一个整型数据分配一个内存空间,并

让pNumber指向这个新内存空间。下面是一个新例,这一次是用double双精型:
double *pDouble;
pDouble = new double;
这种格式是一个规则,这样写你是不会错的。
但动态分配又和前面的例子有什么不同呢?就是在函数返回或执行完毕时,
你分配的这块内存区域是不会被删除的所以我们现在可以用动态分配重写上面的
程序:
#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始终指着有用的信息,这是因为了动态分
配。但是你再仔细读读上面这个程序,虽然它得到了正确结果,可仍有一个严重
的错误。



分配了内存,别忘了回收

太复杂了,怎么会还有严重的错误!其实要改正并不难。问题是:你动态地
分配了一个内存空间,可它绝不会被自动删除。也就是说,这块内存空间会一直
存在,直到你告诉电脑你已经使用完了。可结果是,你并没有告诉电脑你已不再
需要这块内存空间了,所以它会继续占据着内存空间造成浪费,甚至你的程序运
行完毕,其它程序运行时它还存在。当这样的问题积累到一定程度,最终将导致
系统崩溃。所以这是很重要的,在你用完它以后,请释放它的空间,如:
delete pPointer;
这样就差不多了,你不得不小心。在这你终止了一个有效的指针(一个确实
指向某个内存的指针)。
下面的程序,它不会浪费任何的内存:

#include <iostream.h>

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



分配了内存,别忘了回收

太复杂了,怎么会还有严重的错误!其实要改正并不难。问题是:你动态地
分配了一个内存空间,可它绝不会被自动删除。也就是说,这块内存空间会一直
存在,直到你告诉电脑你已经使用完了。可结果是,你并没有告诉电脑你已不再
需要这块内存空间了,所以它会继续占据着内存空间造成浪费,甚至你的程序运
行完毕,其它程序运行时它还存在。当这样的问题积累到一定程度,最终将导致
系统崩溃。所以这是很重要的,在你用完它以后,请释放它的空间,如:
delete 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;
} 

只有一行与前一个程序不同,但就是这最后一行十分地重要。如果你不删除
它,你就会制造一起“内存漏洞”,而让内存逐渐地泄漏。
(译者:假如在程序中调用了两次SomeFunction,你又该如何修改这个程序
呢?请读者自己思考)
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章