一、指针传递
在C++中,使用指针作为函数参数的主要目的是为了传递大型数据结构或者允许函数修改调用者的变量。这样做可以避免在函数中复制大型数据结构,从而提高效率。另外,使用指针还可以使函数修改传入的指针本身,使其指向不同的地址或对象。
变量形式、函数原型及对应传参形式:
- 变量:int a = 0; int *b = 0;
- 函数原型:void func(int *arg);
- 传参形式:func(&a); func(b);//函数调用时实参传入的是地址
函数的参数类型是int指针类型,接受参数的一个地址。因此,对于普通变量a,需要先用&符号取地址后传入,故传入&a。对于指针b,指针就是地址,因此直接传入b即可。
在C语言中,以指针作为函数的形参有三个作用:
①使实参与形参指针指向共同的内存空间,以达到参数双向传递的目的,即通过在被调函数中直接处理主调函数中的数据而将函数的处理结果返回其调用者。这个作用在C++中已经通过引用实现了。
②减少函数调用时数据传递的开销。这一作用在C++中有时可以通过引用实现,有时还是需要使用指针。
③通过指向函数的指针传递函数代码的首地址。
习惯上,如果函数体中不需要通过指针改变指针所指向对象的内容,应该在参数表中将其声明为指向常量的指针,这样使得常对象被取地址后也可以作为该函数的参数。
在程序设计中,当某个函数中以指针或引用作为参数都可以达到同样的目的时,使用引用会使程序可读性更好。
void fun(float x, int* ip, float* fp) { *ip = static_cast<int>(x);//取x的整数部分 *fp = x - *ip;//取x的小数部分 } int main() { cout << "输入3个浮点数:" << endl; for (int i = 0; i < 3; i++) { float x,f; int n; cin >> x; fun(x, &n, &f); //实参传入的是地址 cout <<"第"<<i+1<<"个数的整数部分:" << n << " 小数部分:" << f << endl; } return 0; }
输出:
结果分析:
程序中的fun函数采用了两个指针变量作为参数,主函数在调用过程中使用变量的地址作为实参。形实结合时,子函数的ip值就是主函数中的int型变量n的地址。因此,子函数中改变*ip的值,其结果也会直接影响主函数中变量n的值。fp和浮点数f也有类似的关系。
二、引用传递
变量形式、函数原型及对于传参形式:
- 变量:int a = 0; int *b = 0;
- 函数原型:void func(int &arg);
- 传参形式:func(a); func(b);func(*b)
函数的参数类型是引用类型。对于变量a,直接传入a。对于指针b,可以选择传入地址b或者传入b指向的值*b。
void fun(float x, int& ip, float& fp) { ip = static_cast<int>(x);//取x的整数部分 fp = x - ip;//取x的小数部分 } int main() { cout << "输入3个浮点数:" << endl; for (int i = 0; i < 3; i++) { float x,f; int n; cin >> x; fun(x, n, f); cout <<"第"<<i+1<<"个数的整数部分:" << n << " 小数部分:" << f << endl; } return 0; }
输出:
三、值传递
变量形式、函数原型及对应传参形式:
- 变量:int a = 0; int *b = 0;
- 函数原型:void func(int arg);
- 传参形式:func(a); func(*b);
函数的参数类型是int类型,接收的值是int型变量的值。因此,对于变量a,本身就是int型变量,故直接传入。对于指针变量b,是需要用*符号进行解引用获取指针指向的值,故传入*b。
总结:
引用传递和指针传递都是传地址,可理解为实参和形参的内存地址相同,在函数中的赋值操作在函数结束后仍会保留(只要被赋值的变量仍存在)。而值传递传入的是实参的值,调用函数时会进行拷贝操作将实参的值赋予形参,实参和形参的地址不同,因此在函数体内对形参的赋值操作不会改变实参的值。
参考: