指针和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对于释放后的地址空间,会进行统一的赋值操作。
至于为什么,我不是很清楚,在这就不随便说自己的猜想了,如果有哪位大神知道,还望指导一二。