C语言的指针传递和C++的引用传递

首先,C语言没有引用传递。

C++中使用引用传递的方式是在函数的参数前加&号,如:

void Delete_X(LinkList &L, ElemType x)    // 声明

Delete_X(L, 45);    // 使用

C:指针作为参数传入函数中时,是值传递

      示例代码:

#include <stdio.h>

void fun(int *a)
{
	int t = 50;
	a = &t;
	printf("infun:a=%p\t*a=%d\n", a, *a);
}

int main()
{
	int b=10;
	int *a=&b;
	printf("out1:a=%p\t*a=%d\n", a, *a);
	fun(a);
	printf("out2:a=%p\t*a=%d\n", a, *a);
	return 0;
}

    示例结果:

可以看出,指针作为参数传入函数时,只是将指针变量中存储的地址值传入函数,在函数内改变了形参的地址值并不会对函数外的指针产生影响。图解如下:

注意:虽然在函数中改变地址不会对a产生影响,但是修改*a,外部*a的值也会变化,因为函数内部和外部的指针a,a'都指向b,所以只要修改*a就是修改b的值。

C++引用&和上述的指针传递不同,引用传递相当于把变量本身传入函数,而不是新建一个形参接收a的值。所以在函数内外对a进行操作,结果是一致的。

比如上述代码只改动一处:void fun(int* &a)   

结果如下图:

上述原理明白后,举个复杂的例子:

王道数据库的书中有这样一道题:设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。

算法的思想:设 f ( L , x ) 的功能是删除以L为首结点指针的单链表中所有值等于 x 的结点,显然有 f ( L -> next , x ) 的功能是删除以 L -> next 为首结点指针的单链表中所有值等于 x 的结点。

void Delete_X(LinkList &L, ElemType x)
{
	LNode *p;
	if(L==NULL)
		return;
	if(L->data==x)
	{
		p = L;
		L = L->next;
		free(p);
		Delete_X(L, x);
	}
	else
		Delete_X(L->next, x);
}

在C++中使用引用传递,这样的做法是没有问题的。但是在C中使用指针作为参数进行传递就会有问题,因为在删除结点的时候,让L=L->next在函数中修改了L的地址,但是函数外的L地址值没有改变,也就是并没有成功建立删除头结点后的链接,此时free(p)就会造成断链。图示如下:

如果想用C来实现这个代码,可以将传入函数的参数改为指针的指针,代码如下:

void Delete_X(LinkList *L1, ElemType x)
{
	if(*L1==NULL)
		return;
	LNode *p;
	if((*L1)->data==x)
	{
		p = *L1;
		*L1 = (*L1)->next;
		free(p);
		Delete_X(&(*L1), x);
	}
	else
		Delete_X(&((*L1)->next), x);
}

L1->L,将L1传入函数,根据之前的推断,函数内部会构造一个形参L1',L1的值不会受到函数内部的影响。但是在函数内修改L1所指向的L的值,其L值的变化也应用于函数外(因为L1和L1'指向的是同一块内存区域,对这个区域的修改自然不区分函数的内部和外部)。

注意:C这段函数代码不能写   LinkList L = *L1;   让L来代替*L1的写法,看似书写变得简洁,其实相当于还是构造了一个L的形参,对这个形参的修改不会作用到函数外的L上。

发布了5 篇原创文章 · 获赞 0 · 访问量 1221

猜你喜欢

转载自blog.csdn.net/weixin_40908748/article/details/93061985