C++指向指针的指针与动态数组
这里以一维字符数组开篇,
#include <iostream> using namespace std; void main() { char *pc="abc"; cout<<pc<<endl; cout<<(long)pc<<endl; cout<<*pc<<endl; }
输出:
在本例中,字符数组"abc"存在于内存空间的const区域中,指针变量pc存储在内存栈空间内,pc的值为字符数组"abc"的首地址,也就是字符'a'的地址,输出在第二行,而在c++中,输出字符指针就是输出字符串,程序会自动在遇到\0后停止所以在第一行则完整的输出了字符串"abc"。*pc为从内存地址为pc值的空间内取出值,也就是字符'a'。
如果对一个二维字符数组操作,则要用到指向指针的指针。
指针的本质是一个存放其他变量内存地址的unsigned long int型变量,储存于内存栈空间内。这里假设这个变量为a,指针的指针即是存放a在栈空间中地址的long型变量,也储存在栈空间中。
#include <iostream> using namespace std; void main() { char *pc[]={"abc","xyz","sun"}; char **pb=&pc[0]; for(int i=0;i<3;++i) { for(int j=0;j<4;++j) { cout<<*(*(pb+i)+j)<<" "; } } cout<<endl; }
输出:
下面来逐句解析:
char *pc[]={"abc","xyz","sun"};
定义了一个指针数组,为pc[0], pc[1], pc[2],分别存放了三个字符数组的首地址,这里pc[0]存放了'a'的地址值,pc[1]存放了'x'的地址值,pc[2]存放了's'的地址值,而这三个存放地址(long型数值)的指针变量也储存在内存中,因为是long型数组,所以它们在内存中的地址是连续的,也就是&p[0]+1=&p[1],&p[1]+1=&p[2]。
char **pb=&pc[0];
定义了一个指向指针的指针,其本质上指向了内存中一个long型变量,将它的地址储存起来。这样可以理解为,存放'a'地址long型变量的地址被存放在变量pb中,此时,变量pb的值即是指针数组第一个元素pc[0]的地址,pb+1是指针数组第二个元素pc[1]的地址,pb+2是指针数组第三个元素pc[2]的地址。
pb=&pc[0], pb+1=&pc[1], pb+2=&pc[2]
至此,所有的变量在内存中的关系已经建立,可以用一个指向指针的指针pb去访问二维字符数组的任意元素的值与地址。
cout<<*(*(pb+i)+j)<<" ";
pb+i的值为指针变量pc[i]在内存中的地址,*(pb+i)则把该地址中的值取了出来,比如*(pb+1)=pc[1],这里的pc[1]的值是第二个字符串"xyz"的首地址(即字符'x'的地址、为一long型数值),有了'x'的地址即可访问第二个字符数组的任意成员,如需要输出“xyz"的第三个字符'z',则先取得'z'的地址,*(pb+1)+2,然后从找寻存放于该内存地址中的东西(就是字符'z'),通过*(*(pb+1)+2)取得'z'这个字符。
下面应用指向指针的指针定义动态数组
假设有一个矩阵m×n,其动态数组创建函数如下:
void test4(int m,int n) { int **ppTest=new int *[m]; for(int i=0;i<m;++i) { *(ppTest+i)=new int[n]; //*ppTest++=new int[n]; } //ppTest-=m; for(i=0;i<m;++i) { for(int j=0;j<n;++j) { *(*(ppTest+i)+j)=i+j; } } for(i=0;i<m;++i) { for(int j=0;j<n;++j) { cout<<*(*(ppTest+i)+j)<<'\t'; } cout<<'\n'; } for(i=0;i<m;++i) { delete [] *(ppTest+i); } delete [] ppTest; }
Test(3,4);
输出:
int **ppTest=new int *[m];
先定义一个具有m个元素的指针数组,本质上是在内存堆空间中定义了个具有m个元素的long型数组,将该数组的首地址存于变量ppTest中,该变量位于内存栈空间。
for(int i=0;i<m;++i) { *(ppTest+i)=new int[n]; }
然后逐轮在内存堆空间中定义具有n个元素的整形数组,new关键字返回该数组的首地址,我们所要做的就是用一个变量去接受这个地址的值。ppTest+i为刚才在内存堆空间中申请的具有m个元素的long型数组的第i个变量的地址,把n元素整形数组的首地址填进那个地址的内存空间中,接着就可以用变量ppTest操作整个数组了。如:
*(*(ppTest+i)+j)=i+j;
ppTest+i为存放内存堆空间中第i行的一维整形数组的首地址的指针变量在内存堆空间中的地址,把它的值取出来就可得到第i行一维数组所有元素在内存堆空间中的地址,再通过解引用操作符"*"操作该地址的那片内存空间,这样则实现了通过在栈空间中的指向指针的指针**pb来访问和操作动态数组的所有元素。