【C/C++】理解传值引用和调用引用:函数调用中,为变量赋值,传入其指针;为指针赋值,传入指针的指针

大清早收到消息,好久前写的帖子(链接)下,有人问我问题:

原函数是这样的:

void Attach(int c, int e, Polynomial *pRear){
    Polynomial P;
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    P->coef=c;
    P->expon=e;
    P->link = NULL;
    (*pRear)->link = P;
    *pRear=P;
}
Attach(P1->coef, P1->expon, &rear);

他问,为什么要写成指针呢?写成下面这样不好吗?

void Attach(int c, int e, Polynomial  pRear){
    Polynomial P;
    P = (Polynomial)malloc(sizeof(struct PolyNode));
    P->coef=c;
    P->expon=e;
    P->link = NULL;
    pRear->link = P;
    pRear=P;
}
Attach(P1->coef, P1->expon, rear);

原因很简单,我做出的解答如下:

(1)首先明确 pRear 是一个指针,指向一个结点,那 pRear 本身就是一个地址变量;
(2)其次,明确 C 中都是传值调用。
在你的 Attach(P1->coef, P1->expon, rear) 中:

pRear->link = P;

上面这句话本身是没有问题的,可以对 link 进行赋值。

pRear=P;

但是这句话就不能起到赋值的效果,因为:

  1. 调用 Attach(P1->coef, P1->expon, rear) 时,将rear的值(因为rear是一个指针,所以其值是一个地址变量)赋值一份,给局部变量pRear赋上
  2. 此时 pRear 中保存地址变量,但其本身并不是指向 *rear 的指针;
  3. 换句话说,如果 pRear 的值改变,那么不对 rear 造成影响。
  4. 因此,想要改变 rear 的值,应该将 rear 的地址传入,而非将其本身。

这就涉及到一个基础问题:C/C++中,如何理解传值引用与调用引用?

有很多高手做了很精简凝练的回答,比如下面这个:

链接:只需要记住一句话,传值引用一般就是生成一个临时对象,而引用调用是调用参数本身。

说得对,且对于初学者而言这种理解再好不过。但通过一段时间的深入学习你会发现,所谓“传值引用”与“调用引用”其实是一回事。

对于“传值引用”,假设我们有如下代码:

int x = 0;
int foo(int x):
	x = 10;
	y = 20;
	return y

则调用了 foo(x) 后,x 的值不变,还是 0

但若是“调用引用”,假设我们有如下代码:

int x = 0;
int foo(int *p):
	*p = 10;
	y = 20;
	return y

则调用了 foo(&x) 后,x 的值变化为 10

为什么要加 &* 这么多奇奇怪怪的符号?那就要牵扯到“指针”这个概念了。计算机中,每个变量都要有一个“住址”,就可以理解为变量的“地址”。

小明住在南开路92号,在计算机中的表达为:南开路92号(指针)指向小明(变量)。

在我们的例子中, &x 表示的是 x 的地址; int foo(int *p)表示的是把一个指向 int 类型的指针 p 传入;*p 表示让“ p 本身是一个地址(指针)的前提下, p 所指向的东西”; *p=10 表示让这个地址所指向的变量赋值整数 10

可以看出,对于函数的传参,都是复制该参数的值,然后再传入,即都是“传值引用”。

之所以能做到“调用引用”,是因为对变量的指针进行了“传值引用”,指针的值被赋值,但是复制后其指向的依然是我们要修改的变量。

原创文章 163 获赞 177 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_42815609/article/details/104387966