函数传参:传值,传指针,传引用(C++)
在C语言中调用函数的时候,将实参数据传递给函数的方式,可以分为传值,传指针,以及C++中的传引用。这里所谓的传值,传指针和传引用都是针对实参来说的,也就是传实参的值,实参的指针,实参的引用。
7.5.1 传值
下面是传值的函数定义方式,这是最简单的函数定义与传值方式:
void Func1(int x)
{
x = 1;
}
传值无法改变实参的值,因为传值的情况下,存放在栈上的形参只是实参值的一个拷贝,无法改变实参。
int main(int argc, char* argv[])
{
int a = 0;
Func1(a);
printf("%d\n",a);
return 0;
}
7.5.2 传指针
下面是传指针的函数定义方式,形参x是一个指向整数类型数据的地址。在函数内部通过*运算符来引用实参。
void Func2(int *x)
{
*x = 2;
}
传指针的时候,形参是实参地址的一个拷贝,因此通过*运算符来引用实参,实际上就是实参本身,因此可以通过传指针来修改实参的值。
int main(int argc, char* argv[])
{
int a = 0;
Func2(&a);
printf("%d\n",a);
return 0;
}
7.5.3 传引用
下面是在C++中的传引用调用方式,注意,形参部分使用的是&,而在函数内部,可以直接把形参当做实参来使用,此时形参就是对实参的一个引用。
void Func3(int &x)
{
x = 3;
}
传引用实际上也是传的实参的地址,是可以直接修改实参的。下面是在main函数里直接通过传引用的方式调用函数的方式:
int main(int argc, char* argv[])
{
int a = 0;
Func3(a);
printf("%d\n",a);
return 0;
}
那么C和C++里为什么要提供3种不同的函数传参方式呢?
一,传值不能改变实参,传指针和传引用才能改变实参;
二,传指针和传引用效率比传值要高。因为,传指针和传引用都只是把地址传递给函数,这个过程,只涉及到4个(8个,X64)字节的传输。传值,会随着实参的类型不同,有时候不止传递或者拷贝4个字节。(比如以后要学的结构体和C++对象);
三,传引用比传指针更安全。因为引用一旦初始化,就固定了,不能改变;传引用比传指针简单。因此,传引用既有传指针的高效,又比传指针安全,又有传值的方便。
我们知道,程序中,将2个数交换的一般算法为:
int a = 10;
int b = 15;
int tmp=a;
a = b;
b=tmp;
那么将这段代码封装成一个函数,它的传参却很有讲究:
传值方式:
void swap1(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
void swap2(int *x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
传引用方式:
void swap3(int &x, int &y)
{
int tmp = x;
x = y;
y = tmp;
}
int main(void)
{
int a = 10;
int b = 20;
printf(“a=%d,
b=%d\n”, a, b);
swap1(a, b );//传值,形参是实参值的一个拷贝
printf(“a=%d,
b=%d\n”, a, b);
swap2(&a, &b );//传指针,形参是实参地址的一个拷贝
printf(“a=%d, b=%d\n”, a, b);
swap3(a, b );
printf(“a=%d, b=%d\n”, a, b);
return 0;
}
运行上面的代码,大家会发现,swap1函数无法实现2个数的交换,swap2和swap3可以。这就是因为swap1采用的是传值方式,传值是无法修改实参的,当然就无法交换2个数a和b了,因为交换2个数,就是在修改2个实参的值,必须传指针或者传引用,或者以后通过宏来实现。