多级指针的一个用法是:传递指针参数,如:int GetBinData(char ** data,int &len); 这样定义接口的初衷是,在调用函数之前不知道获得的数据的大小,因而无法准确的开辟合适大小的内存。于是希望在函数内部执行内存的开辟操作,并将开辟的内存地址和大小通过参数返回给调用者(当然我们也可以通过函数返回值来得到新分配的地址)。这里存在一个理解上的误区,我们可能认为传递的一个是一级指针而不是二级。这是错误的,当把某个级别的指针作为同级的指针参数进行传递时,实际执行的是按值传递。当函数返回后该指针仍是指向传递前的地址(就算是该指针的值指向了一个新地址:通过new,但是这个地址不会被带回),亦即原来实参的地址,而不是会待会函数内部所开辟的内存的地址。
如下:
char *buf=0; //buf是一个指针
int len=0;
int rsl=GetBinData(&buf,len); //&buf 是变量buf的地址,其即是一个二级指针
于是函数内部得到了buf的地址,在开辟内存后将新的地址赋予buf:
int GetBinData(char ** data,int &len)
{
//'....
* data=new char[datasize]; //data=0x00186512
//......
}
如果参数使用的是一级指针,data从实参buf得到的地址将是0,这是buf的值,因而这是一个传值过程。而当使用二级指针时,data从实参得到的是buf的地址(一个非0值),此时对buf(*data)的赋值将覆盖原值0。亦即buf得到了在函数内部开辟的内存的地址。另一种理解方式是,使用参数返回函数内部的值必须传递地址(或引用)(可以理解为在内存的地址上进行操作,就像是操作全局变量,因为内存地址是固定的),而buf的地址就是char**(buf的本身已经是char*)。
通过参数分配内存需要两层的指针,而通过返回值分配内存就只需要返回一层的指针