c++ 函数章节总结

Posted tsmeredithh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 函数章节总结相关的知识,希望对你有一定的参考价值。

一、为什么要使用函数?

1. 简化代码,增强程序的可读性。

把一些计算或操作编成通用的函数,以供随时调用,从而避免了代码的重复冗长;简化代码量,对各个部分进行封装,使问题变得简单而且直观,提高了程序的易读性。

2.提升程序的可维护性。

如果我们把主程序拆分成许多个步骤,为每一个功能编写一个函数,那么根据函数的函数名每个函数的功能就非常清晰了。如果我们要修改某一个函数的功能,其他的函数也丝毫不会受到影响。

3.提高团队的开发效率。

设计一个规模很大的程序,它有几千项功能,若把他们都放在一个主函数里,就只能由一个人来编写。但如果我们把这几千项功能分拆为一些函数,分给几百个人去编写,最后用主函数把这些完成的函数组织一下,一个程序就可以很快完工。

4.降低程序执行效率。【缺点】

在程序中运用函数,就需要传递参数,开辟缓存、堆栈等,相比较而言,这个歌过程会耗一些多余的效率。

二、为什么要用函数重载?

【定义】两个以上的函数,具有相同的函数名,但是形参的个数或者类型不同,编译器根据形参和实参的类型和个数的最佳匹配,自动确定调用哪一个函数,称作函数的重载。

  • 重载函数的形参必须不同(形参个数不同或者类型不同)
  • 与返回值的类型无关

    【使用函数重载的好处】

    重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。当函数的编写者充分考虑了不同情况下应该运行稍有不同的函数,函数的使用者就不必为这些小细节而烦恼了。

    【注意】当使用具有默认形参值的函数重载形式时,需要注意防止二义性

    
    void fun(int length,int weight = 2,int height = 33);   //由于weight和height具有默认初始值,只需要一个参数length即可调用函数
    void fun(int length);   //只需要参数length即可调用函数
    /*此时,对于语句fun(1),编译器会指出语法错误*/
    

三、值传递 VS 地址传递 VS 引用传递

1.值传递

形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。

int fun(int x);

2.地址传递

形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作

int fun(int *x);

3.引用传递

形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

int fun(int &x);

4.三种传递方式的比较

【代码】分析三种传值方式函数操作地址的不同


#include < iostream >

using namespace std;
    
//值传递
void change1(int n) {
    cout << "值传递--函数操作地址" << &n << endl;     //显示的是拷贝的地址而不是源地址 
    n++;
}

//引用传递
void change2(int& n) {
    cout << "引用传递--函数操作地址" << &n << endl;  //显示的是源地址(即引用为别名)
    n++;
}
//指针传递
void change3(int* n) {
    cout << "指针传递--函数操作地址 " << n << endl;   //显示的是源地址
    *n = *n + 1;
}
int main() {
    int n = 10;
    cout << " n的地址" << &n << endl<< endl;
    change1(n);
    cout << "值传递结果   n=" << n << endl<< endl;
    change2(n);
    cout << "引用传递结果 n=" << n << endl<< endl;
    change3(&n);
    cout << "地址传递结果 n=" << n << endl<< endl;
    return true;
}

技术图片

【结论】

  • 当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。
  • 当函数内部需要修改参数并且希望改动影响调用者时,采用引用传递或者地址传递。
  • 当一个函数实际需要返回多个值,而只能显式返回一个值时,可以将另外需要返回的变量以地址或者引用传递
    给函数,这样在函数内部修改并且返回后,调用者可以拿到被修改过后的变量,也相当于一个隐式的返回值传递。

四、递归函数

【定义】一种可以直接或间接调用自身的函数(自己调用自己)

  • 递归的边界
  • 递归的逻辑--公式

【例1】阶乘

【分析】阶乘的递归公式为

技术图片

【代码】

#include< iostream >
using namespace std; 
int F(int n){ 
    if(n==0)//递归边界 
        return 1; 
    return n*F(n-1);//递归公式
} 

int main(){ 
    int n; 
    cin >> n; 
    cout << F(n) << endl;
    return 0;
}

技术图片

【例2】汉诺塔

【分析】

技术图片

1)n == 1
         第1次  1号盘  A---->C       sum = 1 次
2) n == 2
         第1次  1号盘  A---->B
         第2次  2号盘  A---->C
         第3次  1号盘  B---->C        sum = 3 次
3)n == 3
            第1次  1号盘  A---->C
            第2次  2号盘  A---->B
            第3次  1号盘  C---->B
            第4次  3号盘  A---->C
            第5次  1号盘  B---->A
            第6次  2号盘  B---->C
            第7次  1号盘  A---->C        sum = 7 次
  • 假设A为存放盘子的塔,B为目标塔,C为辅助塔,算法分为三步:
  • step1:将A上n-1个盘子全部放到C塔上
  • step2:将A上剩下的一个盘子放到B塔上
  • step3:将C塔上的盘子全部放到B塔上

【代码】

#include<iostream>
using namespace std;

void move(char src, char dest) {   //移动函数
    cout << src << "-->" << dest << endl;
}

void hanoi(int n, char src, char mid, char dest) {
    if (n == 1) move(src, dest);
    else {
        hanoi(n - 1, src, dest, mid);  //把上面的n-1个移动到备用柱子
        move(src, dest);    //把第n个移动到目标柱子
        hanoi(n - 1, mid, src, dest);   //把备用柱子上的n-1个移动到目标柱子
    }
}

int main() {
    int m;
    cout << "enter the num:";  //输入环个数
    cin >> m;
    hanoi(m, 'A', 'B', 'C');
    return 0; 
}

技术图片

以上是关于c++ 函数章节总结的主要内容,如果未能解决你的问题,请参考以下文章

更新:C++ 指针片段

2C++ 的升级

inline内联函数

这些 C++ 代码片段有啥作用?

有趣的 C++ 代码片段,有啥解释吗? [复制]

学习c++:错误:使用已删除函数