空指针、void*指针、new及delete

来源:互联网 发布:linux内核进程调度 编辑:程序博客网 时间:2024/05/01 12:07

如题分别总结这些和指针有关的一些知识点


1. 指向任意类型的指针void*

很多人误以为void*类型的指针就是空指针,这是不对的。void*型指针,表示定义一个指针,但不指定它指向那种类型的数据。void*类型的指针作为一种通用的指针,可以和其他任何类型的指针(函数指针除外)相互转化而不需要类型强制转换,但不能对它进行解引用及下标操作。

也就是说声明了一个void*类型的指针后,可以把任意类型的数据地址赋给该指针,但并不改变该指针的void*类型。要通过解引用访问void*指针指向的数据,就必须要先把void*指针强制转换成指向的数据类型的指针,然后再解引用访问数据。这是因为void*指针并不知道指向的数据类型的长度,所以不能直接访问数据。

第二点,如果声明了一个void*指针而没有初始化,那么该指针指向的地址是未知的,而不是NULL。


2. 空指针

空指针就是指向空地址的指针,空指针的值为0或NULL(可参照下面程序的运行结果),这个指针值对任意类型的指针都是合法的。也就是说任意类型的指针都可以初始化或置为空指针。空指针表示该指针目前处于闲置状态,没有指向任何有意义的东西。另外,空指针虽然指向“空”,但它本身作为一个数据类型的单位,是要占用内存空间的。


3. 野指针

没有初始化,并且不知道指向地址的指针就是野指针。由于野指针指向的地址未知,因此对野指针指向的地址进行写操作有可能发生未知的错误,这是非常危险的。在vs2010平台下,经过我的实验,对野指针进行访问也是非法的。以后使用指针一定要记住赋初值或在程序中赋值,否则很可能出现一些意想不到的结果。


4. new和delete

c++的动态内存分配使用new关键字,具体用法为:

typename* pt = new typename; 或者对于数组:

typename* ps = new typename [ArSize];

new关键字告诉编译器找到一块长度合适的内存块,返回首地址赋值给指针pt。该内存块保存的值由指针pt访问。

为了防止内存泄露问题出现,需要使用delete运算符来释放使用完的内存:

delete pt; 对于数组:

delete [] pt;

需要注意的是使用delete释放内存后,编译器分配给指针的内存被释放,但是指针指向的地址并不会被改变,并且这个地址仍可以被指针访问到!比较保险的做法是,释放完内存后,将指针置位空:pt = NULL,这似乎是没有区别的,但是对于一些复杂的需要大量判断的程序来说却有极大的好处,例如下述程序块:

int* pt = new int [10];...if(pt != NULL){delete [] pt;pt = NULL;}...
这样避免了重复释放内存块的危险。


下面一个程序验证了空指针值,被释放后的指针值是否变化,以及释放内存后指针指向的内存仍可以被访问到。

注:声明的pt、ps指针都需要初始化,否则被cout访问报错。

#include <iostream>using namespace std;int main(){void* pt = NULL;void* ps = NULL;cout << "Value of pt: " << pt << endl<< "Value of pd: " << ps << endl;pt = new int;ps = new int [10];cout << "Value of pt: " << pt << endl<< "Value of pd: " << ps << endl;delete pt;delete [] ps;cout << "Value of pt: " << pt << endl<< "Value of pd: " << ps << endl;*((int *)pt) = 10;cout << pt << ": " << *((int *)pt) << endl;return 0;}
运行结果:

0 0