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

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


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;
}
运行结果:

请参考我给出的代码框架,实现对EMPLOYEE结构体为数据的双向链表的排序算法,要求按照按employeeId升序排列 typedef struct linkNode { void* data; //使用空指针使得NODE适配多种数据结构 struct linkNode* preNode; struct linkNode* nextNode; }LINKED_NODE; /*Define the struct of double linked list.*/ typedef struct { LINKED_NODE* head; LINKED_NODE* tail; size_t size; }DOUBLE_LINK_LIST; typedef struct { int employeeId; char name[20]; char ipAddress[30]; char seatNumber[20]; char group[10]; } EMPLOYEE; DOUBLE_LINK_LIST* createDoubleLinkedList() { DOUBLE_LINK_LIST* newList = (DOUBLE_LINK_LIST*)malloc(sizeof(DOUBLE_LINK_LIST)); newList->head = NULL; newList->tail = NULL; newList->size = 0; return newList; } void destroyDoubleLinkedList(DOUBLE_LINK_LIST* list) {} /*Add a new node before the head.*/ void insertHead(DOUBLE_LINK_LIST* list, void* data) // void执政适配其他data类型? {} /*Add a new node after tail.*/ void insertTail(DOUBLE_LINK_LIST* list, void* data) // 如何适配其他data类型? {} /*Insert a new node.*/ void insertNode(DOUBLE_LINK_LIST* list, void* data,int index) // 如何适配其他data类型? {} void deleteHead(DOUBLE_LINK_LIST* list) {} void deleteTail(DOUBLE_LINK_LIST* list) {} void deleteNode(DOUBLE_LINK_LIST* list, int index) {} LINKED_NODE* getNode(DOUBLE_LINK_LIST* list, int index) {} /* 遍历链表,对每个节点执行指定操作*/ void traverseList(DOUBLE_LINK_LIST* list, void (*callback)(void*)) { LINKED_NODE* currentNode = list->head; while (currentNode != NULL) { callback(currentNode->data); currentNode = currentNode->nextNode; } } void printEmployee(void* data) {}
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值