指针和delete浅谈

指针是一个很神奇的变量,在我看来,以指针为基础,可以延伸出三个值。

1 指针的地址

2 指针的值

3 指针指向的值

有的人或许认为指针指向的值其实和指针本身并不是直接相关连的。

但是其实这个特性确实我们在编程中经常使用的,所以我就把他加了进来。

在介绍之前,如果您对这里已经足够了解并且有兴趣看看我说了什么,那么请跳过这一段~

什么是指针的地址?

指针的也是一个变量,在三十二位计算机中,指针占有四个字节的内存空间,正好可以指满32位机中左右的内存单元。

所以,很自然的,指针也有一个属于自己的地址。

如果你定义一个指针,比如这样:

int *ip;//int pointer

那么获取其地址的方式就是将ip视为一个普通变量,然后用取地址符获取其地址:

cout<<&p<<endl;

这样就在屏幕中打印出了这个指针变量在内存单元中的地址。

这个地址在该进程的生命周期中是不会改变的,因为指针本身只是一个常规变量。

什么是指针的值呢?

之前已经说了,指针是一个变量,是变量,都会存贮一个值。

那么如何查看一个指针的值呢?

我们可以这样理解一下。

用上面已经定义的ip为例。

假设我已经定义了另一个变量:int temp;

使指针ip指向temp的表达式如下:

ip=&temp;

我们都知道&temp获取的是temp的地址,那么从表达式就可以知道,其实,ip本身,就表示temp的地址,也就是ip的值。

所以,直接输出就可以了

cout<<ip<<endl;

最后一个,也是用的比较多的,就是指针指向的值。

为了方便,还是用上面的ip和temp。

ip指向temp,那么获取temp的值,就可以通过ip中存储的地址值来获取temp的值。

如果你学过汇编,那么这是一个很简单的工作。

而在C语言中,这一过程将更加简单,只要在指针前加一个'*'号,问题就轻松解决。

也就是说*p可以当成temp用。

当然,指针的用途不仅仅局限于此,指针还可以用于函数间数据的共享处理,以及开辟新的内存单元,调用函数,直接从某一出地址开始执行程序。

至于引用,我只能说C++中的引用就是一个只读的指针,在参数传递的时候编译器很聪明的做了一些让开发者省力气的工作,别的,我还真没发现什么。

而至于讲delete,就必须要讲到new。

C++中的new的作用相当C中的malloc,顾名思义,即memory allcoc。

new用于内存分配和布局,功能强大,而且比malloc要简练不少。

还是上面的那个指针,就可以通过这种方式为其开辟一小块内存单元:

ip=new int;//如果是数组的话,加上[N]

这样ip就获取了一块大小为int的内存单元。

如何清理呢?

这时就用到了delete。

操作也很简单,只要将需要释放的内存单元的指针放在delete后面就可以了

delete ip;

似乎到这里工作就已经结束了,但是昨天的一个队列清除的函数让我有了一个想法,而这个想法和delete有很大的关系。

如果我想要清除一个队列,能不能只用队列的头指针呢?

如果delete只是返回一个记录,将相应的内存空间返还给Os,而不修改其值的话,那么这种想法将是可能的。

所以我做了这样的尝试:

 

    int *p=new int;
    int t=10;
    p=t;
    cout<<&p<<endl
        <<*p<<endl
        <<p<<endl;
    delete p;
    cout<<&p<<endl
        <<*p<<endl
        <<p<<endl

  输出结果截图所示:

在这里可以发现,在经过delete之后,尽管指针的只没有变,但是指向的内存空间的值已经跑飞了……

在结构体代码测试的时候,也是如此。

代码是这样的:

 1 struct Ntemp *temp1=newNtemp;//struct Ntemp{int a;struct Ntemp *next;};
 2     temp1->a=320;
 3     temp1->next=new Ntemp;//the value of next is changed
 4     cout<<(int *)temp1<<endl;
 5     cout<<temp1->next<<endl;
 6     cout<<temp1->a<<endl;
 7     delete temp1;//delete it
 8     cout<<(int *)temp1<<endl;
 9     cout<<temp1->next<<endl;
10     cout<<temp1->a<<endl;

运行结果却是这样的:

可以发现,当temp1指向的内存空间被释放掉后,temp1本身的值并没有改变,而temp1的next指针的值却发生了变化。

也就是说,next不再指向专门为其开辟的地址空间。

尽管temp1的地址值没有变,但是其指向的内存空间的值,被改变了。

那是不是因为next指针不是原来的那块空间呢?

这里我专门测试了一下,可以讲上面的代码进行一点点的修改,把第五行和第九行的本值输出改为地址输出。

你会发现,其值并没有改变,而且地址相对于temp1的偏移量就是4个字节,一个int值的大小(就是a的空间)。

所以delete删除一个结构体的时候,并不会修改指针本身的值,但会改写其指向地址空间的值。

所以,单个指针清空队列,是不可行的。

这里应该本篇已经到尾声了,但是有一个很有意思的事情就是,每次程序的输出后,next的低16位的值都是一样的。

比如这个:

和上面的输出结果对比,你会发现第五行的值是一样的。

这个似乎表明,delete对于释放后的地址空间,会进行统一的赋值操作。

至于为什么,我不是很清楚,在这就不随便说自己的猜想了,如果有哪位大神知道,还望指导一二。

posted @ 2012-10-05 09:59  Matrix_R  阅读(3552)  评论(7编辑  收藏  举报