函数的递归调用
一个函数直接或间接地调用自己,就叫做递归调用。如下求 n 的阶乘的例子:
分析:n! 的计算有两种情况:1)n = 0 时,n! 为1;2)n > 0 时,n! = n(n - 1)! 。
//计算 n 的阶乘
unsigned fac(unsigned n) {
unsigned f;
if (n == 0) {
f = 1;
}
else {
f = fac(n - 1) * n; //调用了自己
}
return f;
}
函数的参数传递
函数没有被调用的时候,形参是不占有实际的内存空间的。在函数被调用的时候,才为形参分配存储单元,且将实参与形参相结合(参数传递)。参数传递的方式有值传递和引用传递。
- 值传递
形参获得值以后,就与实参脱离关系。此后形参的变化不会影响到实参。例如:
void fac(int a) {
a++; //形参值发生改变
}
int main() {
int a = 5;
fac(a);
cout << a; //此时a的值还是5,fac对形参a的操作不影响实参a
return 0;
}
- 引用传递
引用变量是另一个变量的别名。例如:
int i;
int &ri = i; //创建一个int型的引用ri,并把它初始化为变量i的一个别名
int j = 10;
ri = j; //表示把j的值赋给i,而不是ri成为j的别名
注意:1)声明一个引用时,必须进行初始化;2)一个引用被初始化以后,不能再指向其他对象(这点与指针不同)。
引用作为形参,就是引用传递。修改值传递中的例子:
void fac(int &a) {
a++;
}
int main() {
int a = 5;
fac(a);
cout << a; //此时a的值为6
return 0;
}
内联函数
编译时将函数体嵌入到每一个调用处。如下计算圆的面积:
const double PI = 3.1415926536;
//内联函数,根据圆的半径计算面积
inline double calArea(double r) {
return PI * r * r;
}
int main() {
double r = 3.0;
//调用内联函数。编译的时候这里被替换为内联函数的函数体
double area = calArea(r);
cout << area << endl;
return 0;
}
--------------------
运行结果:
28.2743
注意:
- 编译器不承诺将inline修饰的函数作为内联。
- 内联函数的操作要定义得简单一些。
- 没有inline修时的函数也可能被编译为内联。
- 如果将内联函数定义得比较复杂,则大多数编译器会自动将它转换为普通函数处理。
含有默认形参值的函数
函数在定义时可以预先声明默认的形参值。例如下面的add方法:
int add(int x = 5, int y = 6, int z = 7) {
return x + y + z;
}
int main() {
add(10, 20, 30); //实现了 10 + 20 + 30
add(10); //形参x采用了实参10,形参y和形参z分别使用默认值6和7,最终实现了 10 + 6 + 7
add(10, 20) //形参x和y分别采用了实参10和20,形参z使用默认值7, 最终实现 10 + 20 + 7
add(); //x、y和z都使用默认值,实现了 5 + 6 + 7
}
注意两个事项:
- 有默认值的形参要靠右放。如下例子:
int add(int x, int y = 5, int z = 6); //正确
int add(int x = 1, int y = 5, int z); //错误
int add(int x = 1, int y, int z = 6); //错误
- 函数在定义之前有原型声明,则形参默认值在原型声明处给出,定义出不能再出现默认形参值。如:
int add(int x = 5, int y = 6); //原型声明给出形参默认值
int main() {
add();
return 0;
}
int add(int x, int y) { //函数定义处不写默认值
return x + y;
}