首先,先区分下数组指针和指针数组:
数组指针(也称行指针)
标准格式:A (*p)[num]
(A为数据类型,num为无符号整数)
解释:因为()优先级别高,所以我们可以看出(*p)是一个一维指针,
把(*p)看作整体 ,从(*p)[num]我们可以看出它是一个一维的数组指针,
并且是A数据类型的,num表示该指针的步长, 所以p+1表示指针跳过num个元素,
在实践中,我们常拿来这样用:int (*p)[3] = new int[2][3];
所以p + 1跳过了第一行2个元素从而指向下一行的第一个元素p[1][0],故而称作行指针.
指针数组
参考格式: A *p[num];
(A为数据类型,num为无符号整数)
[ ]优先级高,先与p结合成为一个数组,再由A*说明这是一个A数据类型的指针数组,
它有n个指针类型的数组元素。
这里执行p+1是错误的,这样赋值也是错误的:p=a;
因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。
但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。
介绍完数组指针和指针数组后,我们用一个ClassA类的new分配和delete来说明使用示例:
//ClassA.h
#ifndef H_ClassA
#define H_ClassA
#include<iostream>
using namespace std;
class ClassA
{
public:
ClassA(): m_ObjectIndex(m_ObjectNum)
{ m_ObjectNum++; cout << "ClassA:构造函数" << endl; };
virtual ~ClassA(){ m_ObjectNum--; cout << "ClassA:析构函数" << endl; };
void coutObjectIndex() const { cout << "ClassA对象索引:" << m_ObjectIndex << endl; }
void coutObjectNum() const { cout <<"ClassA对象数量:" <<m_ObjectNum << endl; }
private:
int m_ObjectIndex;
public:
static int m_ObjectNum;
};
int ClassA::m_ObjectNum = 0;
#endif
//main.cpp
#include<iostream>
using namespace std;
#include "ClassA.h"
int main(char argc, char* argv[])
{
//------------【前三组对象】----------------
ClassA a; //初始一个类对象
a.coutObjectIndex();
a.coutObjectNum();
a.~ClassA(); //直接调用析构函数释放对象内存空间
cout << endl;
ClassA* p = new ClassA; //指针指向一个new分配的对象首地址
p->coutObjectIndex();
p->coutObjectNum();
delete p; //用delete释放对象堆空间
cout << endl;
ClassA* point = new ClassA[2]; //用new分配10个对象,并用指针指向首地址
for (size_t i = 0; i < 2; i++)
point[i].coutObjectIndex();
point->coutObjectNum();
delete[] point; //delete释放数组形式的对象队空间
cout << endl;
//----------------【数组指针】-------------------
ClassA(*arrPoint)[3] = new ClassA[2][3];//用new分配2*3个对象,并用指定列数为3的数组指针指向首地址
for (size_t i = 0; i < 2; i++)
arrPoint[i]->coutObjectIndex();
for (size_t i = 0; i < 2; i++)
for (size_t j = 0; j < 3; j++)
arrPoint[i][j].coutObjectIndex();
arrPoint[0][0].coutObjectNum();
delete arrPoint; //数组指针其实是一个指针, 其指向是一片连续的堆空间,调用一次即可
cout << endl;
//---------------【一维指针数组】----------------
ClassA* pointArr[3]; //构建维度为3的指针数组,并使其每一个元素指向一个new分配2维数组对象的首地址
for (size_t i = 0; i < 3; i++)
{
pointArr[i] = new ClassA[2];
for (size_t j = 0; j < 2; j++)
pointArr[i][j].coutObjectIndex();
}
pointArr[0]->coutObjectNum();
for (size_t i = 0; i < 3; i++) //对指针数组每一个元素指针,调用 delete[]
delete[]pointArr[i];
cout << endl;
//---------------【指向指针数组的二维数组】---------
ClassA** twoDimPoint = new ClassA*[3]; //用new分配一个3维的指针数组对象,并用二维指针对象指向它的首地址
(*twoDimPoint)->coutObjectNum();
for (size_t i = 0; i < 3; i++)
{
twoDimPoint[i] = new ClassA[2]; //继续用new分配2维的对象,并用指针数组元素指向首地址
for (size_t j = 0; j < 2; j++)
twoDimPoint[i][j].coutObjectIndex();
}
twoDimPoint[0][0].coutObjectNum();
for (size_t i = 0; i < 3; i++) //对一维指针数组每一个元素指针,调用 delete[]
delete[] twoDimPoint[i];
delete[] twoDimPoint; //释放二维指针所分配的堆空间
cout << endl;
cout <<"为验证所有对象清理完毕, 输出最后剩余对象数量:"<<ClassA::m_ObjectNum<<endl;
getchar();
return 0;
}
main.cpp中注释说的比较清楚,相信大家能理解,这里我就不做过多说明了~
最后附上程序结果图,大家自己也可以运行看看:
【前三组对象】:
【数组指针】:
【一维指针数组】:
【指向指针数组的二维数组】: