一 :关于指针和堆的内存分配
指针数组 : 一个数组里放的都是指针,我们把他叫做指针数组
int * a[10]; 由于它是一个数组,他是不能从堆空间里申请空间的。 只能做个循环,每个元素去申请空间,或者每个元素去指向另外的地址空间。
数组指针 : 一个指向一唯或者多唯数组的指针;
int * b=new int[10]; 指向一唯数组的指针b ;
一些例子:
int (*b2)[10]=new int[10][10]; 注意,这里的b2指向了一个二唯int型数组的首地址.
注意,这里的b2的类型是int (*) ,这样表示一个指向二维数组的指针。再注意,如果这样在堆空间里已经申请了内存,在释放内存的时候要保证每个空间都要释放。 b2是有长度为10的每一个元素是一个int*指针,每一个int*指针指向一个int[10]的数组
int (**b3)[2]=new (int(*)[2])[2]; b3表示一个指向(指向二唯数组的指针)的指针,我们在给他申请空间的时候一定要注意它的类型:它是int (*)型的指针,那申请空间的时候的类型为int(*)[元素个数],由于它后边还带个二唯数组每元的个数后缀,所以加上这个后缀就OK了。
int (**b4)[2];表示每一个元素都指向(指向二唯数组的指针)的数组。
(3) 指向了一个(指向指针的指针)
int ** cc=new (int*)[10];
这种声明很简单因为cc的类型是int*型的指针,所以你要在堆里申请的话就要用(int *)来申请;
(4) 多唯指针数组的指针数组。
int ** d[2];表示一个指向指针的指针数组;数组里有两个元素,每一个元素都是一个指针,这个指针指向另一个指针:)
在理解的时候首先看到2,那么表示这个数组中有两个元素,再看类型,表示数组中每一个元素是int**类型,是指向指针的指针,那么申请内存的时候为每一个元素对应生成指针的指针,如果一次性指向,就需要指向一个指针的指针的数组
再怎么变也是数组呀,呵呵,
如果你读懂了上边的,那下边的声明就很简单了:
d[0]=new (int *)[10];
d[1]=new (int * )[10];
---------------------------------------
总结 : 只要知道了其中的指针类型,声明一个指针就很简单了,堆里申请稍微复杂点,不过知道了类型,也就稍微烦琐一点。
(1)int*ptr;//指针所指向的类型是int
(2)char*ptr;//指针所指向的的类型是char
(3)int**ptr;//指针所指向的的类型是int*
(4)int(*ptr)[3];//指针所指向的的类型是int()[3]
二 : 函数指针
关于函数指针,我想在我们可能需要写个函数,这个函数体内要调用另一个函数,可是由于项目的进度有限,我们不知道要调用什么样的函数,这个时候可能就需要一个函数指针;
int a();这个一个函数的声明;
ing (*b)();这是一个函数指针的声明;
让我们来分析一下,左边圆括弧中的星号是函数指针声明的关键。另外两个元素是函数的返回类型(void)和由边圆括弧中的入口参数(本例中参数是空)。注意本例中还没有创建指针变量-只是声明了变量类型。目前可以用这个变量类型来创建类型定义名及用sizeof表达式获得函数指针的大小:
unsigned psize = sizeof (int (*) ()); 获得函数指针的大小
// 为函数指针声明类型定义
typedef int (*PFUNC) ();
PFUNC是一个函数指针,它指向的函数没有输入参数,返回int。使用这个类型定义名可以隐藏复杂的函数指针语法,就我本人强烈建议我们大内弟子使用这种方式来定义;
int
(*(*f4())[10]();的声明,f4是一个返回指针的函数,该指针指向了含有10个函数指针的数组,这些函数返回整形值;不是这个函数有特别之处,而是Bruce Eckel 说的“从右到左的辨认规则”是一种很好的方法,值得我们去学习
-------------------------------
写在最后面,很重要:
在Effective C++中提到
如果在new表达式中使用了[],那么在对应的delete的表达式中也需要[],反之如果没有用到,那么都不使用