函数调用的背后非常基本,对应着CPU可以进行的四种基本运算之一。//哪四种呢?
a.数据传输b.基本运算c.函数调用的return机制d.循环分支中的指令跳转。
接下来以交换函数的调用为例,说清楚传值调用/指针调用/引用调用的本质区别。
先明确下几个概念:
a.形参:出现在函数定义中,只能在自己的函数体内部可以使用。因为形参变量只有在被调用时才被分配内存单元。调用结束,即刻释放。返回主调函数后则不能使用该形参变量。
b.实参:出现在主调函数中,实参如果是变量的话进入被调函数后,变量也不能使用。
实参可以是常量、变量、表达式、函数等,无论何种类型,它们都必须有特定的值,以便传值给形参。
c.引用:变量名称是变量附属在内存位置中的标签,引用当成是变量附属在内存位置中的第二个标签。
d.函数调用:模块化编程的主要实现手段,每一个模块对应一个或多个函数,实现一种功能。提高开发、维护效率。
//pass by value
void swap(int x, int y){
int t;
t = x; x = y; y = t;
}
int main(){
int a(5), b(10);
cout<<"before: a = "<<a<<"b = "<<b<<endl;
swap(a, b);
cout<<"after: a = "<<a<<"b = "<<b<<endl;
return 0;}
/**/函数调用过程中,形参x,y 是复制了a, b的值的新变量,原变量a,b没有被动**
//pointer as formal params
void swap(int*x, int*y){
int t;
t = *x; *x = *y; *y = t;
}
int main(){
int a(5), b(10);
cout<<"before: a = "<<a<<"b = "<<b<<endl;
swap(&a, &b);
cout<<"after: a = "<<a<<"b = "<<b<<endl;
return 0;
}
//函数调用过程中,地址在&a和&b的两块内存所存储的值发生了交换。
//reference as formal params
void swap(int& x, int& y){
int t;
t = x; x = y; y = t;
}
int main(){
int a(5), b(10);
cout<<"before: a = "<<a<<"b = "<<b<<endl;
swap(a, b);
cout<<"after: a = "<<a<<"b = "<<b<<endl;
return 0;
}
//函数调用过程中,引用名叫x和y的两块内存所存储的值发生了交换。而x与a是同一变量; y与b是同一变量。
可以把内存当成是一个容器。变量名相当于是容器的名字(标签),变量初始化相当于向容器里装东西,变量的值相当于容器内容物;引用相当于是容器的第二个标签;指针是容器的地址编码。
按值传递:形参被初始化为实参的值(要分配新内存),形参对应的容器内容物发生交换,调用完毕后形参释放,不影响实参。
按引用传递:引用类型的形参相当于标签,函数调用时,标签贴在了容器上(不用分配新内存。引用变量的声明必须初始化,和一个普通变量绑在一起)。交换标签的背后本质上是交换容器的内容物。(想象交换两个装满白酒和啤酒的酒杯)
按指针传递:指针相当于内存的地址编号,函数调用时交换地址编号的背后还是交换容器内容物。