本质:指针本身也是一个值,它的值是所指向对象的地址。指针传递参数本质上是值传递的方式,它所传递的是一个地址值。
值传递过程中,函数在栈中开辟区域存放形参,形参接受实参传递过来的值。例如调用函数时传递指针p,p指向某一内存区域,假设指针p的值为0x0121E680,那么函数的形参pp接受到的也为0x0121E680,即在栈中开辟一个区域存放指针pp,其值为0x0121E680。
此时若有一个局部变量a=3,在函数中执行pp=&a,即让形参pp指向a所在的地址,那么在函数内部pp的值不再为0x0121E680,而是变为了a的地址,可是实参p指向的内存区域并没有发生改变,pp只是p的一个副本,当函数结束之后返回时,原来的实参p并没有改变,因为p所指向的内存地址始终没有变,变的是函数内形参指向的内存地址,当函数调用结束后,该内存被释放,导致实参没有改变。
但是如果传递的是一个数组,过程同上,函数创建一个地址副本,其值为数组首地址,若此时将形参指向另一个数组,那么实参不会改变。若形参改变数组中某一个数据的值,由于形参和实参此时指向的是同一块内存区域,实参的改变会导致形参的改变,函数返回后数组中该值仍然被改变。
链表同理,若函数内仅仅只是将链表头指针变为空,则实参不会体现。若将链表某一个节点的值改变,则会体现到实参中。
解决方案:1.传递指针的地址,即双重星号
传递参数时传递地址的地址,void work(int **pp),调用时work(&p),这样在函数形参pp所得的也是地址的地址,此时若有一个指针a,使用*p=a,可以顺利改变实参的值。
2.使用引用
void work(int *&pp),调用时work(p),也可以达到目标。