文章插图
1 引言举个例子: 在func函数退出后,指针pInt所指的内容*pInt为 12
#include <stdio.h>//公众号:C语言与CPP编程int func(int* pRes){ if(pRes == NULL) pRes = new int(12);//分配新的内存空间给指针pRes,并赋值 return 0;}int main (){ int *pInt = NULL; int val = func(pInt); printf("%dn",*pInt); return 0;}
解析:int func(int* pRes)函数的形参是指针类型 int *pRes,在函数体中 new了一块内存并赋值 12,将内存地址赋值给指针 pRes 。在main函数中,定义了指针pInt,调用func函数,把pInt作为参数传入func函数中 。结果*pInt并不是 12 。原因:在func函数调用过程中,形参和实参的传递使用了值传递方式,这种情况下,形参变量在函数体内发生了变化,在函数结束之后,形参变量随之释放,不能把变化的结果返回给实参 。
可以使用指针传递或者引用传递 。想要在函数体内改变pRes的值,并把这个变化返回到main函数中,必须传递pRes的指针 。因为pRes本身就是指针,所以应该传递指针的指针,或者指针的引用 。
指针的引用【c语言指针变量的传值和传址】
int v = 1;int *p = &v;'int *&rp = p;
&说明r是一个引用 。*确定r引用的类型是一个指针 。因为引用不是对象,故无引用的数组,无指向引用的指针,无到引用的引用:
int& a[5]; // 错误int&* p; // 错误int& &r; // 错误
所以修改函数int func(int* pRes);为int func(int *&pRes);#include <stdio.h>int func(int* &pRes){ if(pRes == NULL) pRes = new int(12);//分配新的内存空间给指针pRes,并赋值 return 0;}int main (){ int *pInt = NULL; int val = func(pInt); printf("%dn",*pInt); return 0;}
2 传值、传引用区别和联系传值:实参拷贝传递给形参 。就是把实参赋值给形参,赋值完毕后实参就和形参没有任何联系,对形参的修改就不会影响到实参 。传地址:把实参地址的拷贝传递给形参 。就是把实参的地址复制给形参 。复制完毕后实参的地址和形参的地址没有任何联系,对实参形参地址的修改不会影响到实参, 但是对形参地址所指向对象的修改却直接反应在实参中,因为形参指向的对象就是形参的对象 。
传引用:本质没有任何实参的拷贝,两个变量指向同一个对象 。这是对形参的修改,必然反映到实参上 。
- 无论传值还是传指针,函数都会生成一个临时变量,但传引用时,不会生成临时变量,
- 传值时,只可以引用值而不可以改变值,但传值引用时,可以改变值,
- 传指针时,只可以改变指针所指的内容,不可以改变指针本身,但传指针引用时,既可以改变指针所指的内容,又可以改变指针本身,
- 引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数 。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好 。
推荐阅读
- GO语言 GUI编程 | 怎样实现 page 页面?
- 使用 Go 语言实现凯撒加密
- C语言中的动态内存分配与变长数组
- C语言标准库的7类函数
- 天文航天|外国航天员来中国空间站用什么语言交流?专家给出回应
- 中国人最难学的语言 中国最难的语言
- PLC编程语言之争:谁才是"一哥"
- Go语言规范你掌握多少?这道题检验一下
- go语言137道面试题整理汇总
- 你所不知道的C语言高级用法