最近做C++开发,ACE库函数的很多形式参数都是指针引用,在这上面吃了一些亏,花时间写了一个demo来加深自己对指针,引用,以及把指针当参数,把指针的引用当参数的函数的理解。
先下结论,并不难,花一个小时,跑一下我提供的代码,然后看一下我最后的总结,即可搞懂。
#include "stdio.h"
int var_b = 8;
void func_pt (int* pt_)
{
printf("In func_pt, beforeset the pt_ self address is %X\n", &pt_);
printf("In func_pt, beforeset the pt_ content is %x\n", pt_);
printf("In func_pt, beforeset the var content pointed by pt is %x\n", *pt_);
pt_ = &var_b;
printf("In func_pt, afterset the pt_ self address is %X\n", &pt_);
printf("In func_pt, afterset the pt_ content is %x\n", pt_);
printf("In func_pt, afterset the var content pointed by pt is %x\n", *pt_);
}
void func_pt_ref (int*& pt_ref_)
{
printf("In func_pt, beforeset the pt_ self address is %X\n", &pt_ref_);
printf("In func_pt, beforeset the pt_ content is %x\n", pt_ref_);
printf("In func_pt, beforeset the var content pointed by pt is %x\n", *pt_ref_);
*pt_ref_ = 5;
printf("In func_pt, afterset the pt_ self address is %X\n", &pt_ref_);
printf("In func_pt, afterset the pt_ content is %x\n", pt_ref_);
printf("In func_pt, afterset the var content pointed by pt is %x\n", *pt_ref_);
}
int main ()
{
int var_a = 1;
printf("Var a self address is %x\n", &var_a);
printf("Var a self content is %x\n", var_a);
printf("Var b self address is %x\n", &var_b);
printf("Var b self content is %x\n", var_b);
int* pt;
printf("Before set value, the pt self address is %x\n", &pt);
printf("Before set value, the pt content is %x\n", pt);
printf("Before set value, the var content pointed by pt is %x\n", *pt);
pt = &var_a;
printf("after set value to var_a, the pt self address is %x\n", &pt);
printf("after set value to var_a, the pt content is %x\n", pt);
printf("after set value to var_a, the var content pointed by pt is %x\n", *pt);
// func_pt(pt);
func_pt_ref(pt);
printf("after call func, the pt self address is %x\n", &pt);
printf("after call func, the pt content is %x\n", pt);
printf("after call func, the var content pointed by pt is %x\n", *pt);
}
给出几点结论:
- 先不要把指针当成指针,把指针当作变量。在定义的时候,这个变量就有自己的地址,也有了自己的内容(值),只是其内容(值)存储的是某个地址。
- 当其他变量的地址设置为指针这一变量的值时,通过一个指针可以打印出三个值。分别是a指针变量本身的地址(这个永远不变),b指针变量的值(即其存储的内容–某个地址),还有c指针变量的值所指向的值。
- 不带引用的函数参数传递,本质是把实参的值拷贝到CPU寄存器里,然后复制给被调用函数的形式参数(参见《深入理解计算机系统》)。
- 带引用的函数参数传递,本质是把实参的地址拷贝到CPU寄存器里,然后复制给给被调用函数的形式参数(参见《《深入理解计算机系统》),其实就是把实参进行各种操作。
- 将指针变量作为函数参数,本质类似于3,所以是把实参的值(也就是2中的b),拷贝给形式参数。所以在被调用函数的操作:你可以更改b这个地址的值,但是对实参的b没有任何影响,因为是拷贝给你行参的。也可以更改b这个地址指向的c的值,这时候同样会改变实参的c。
总结来说,就是传入指针变量,还是以更改实参的c为主,对更改实参的b不产生任何影响,因为是拷贝过去。实参的b还是实参的b。 - 将指针的引用作为函数参数,本质类似有4,所以是把实参的地址(也就是2中的a),拷贝给形式参数,所以你会看到行参的a b c跟实参的是一模一样。所以这个时候,你可以更改b这个地址的值,这时候实参的b也跟着更新了。也可以更改b这个地址指向c的值,这时候同样会改变实参的c。
总结来说,就是传入指针的地址,既可以更改实参的b,即更新其指向。可以更新实参的c,即其指向的值。