C++学习(二)_函数中的重要知识点

1.函数的重要性

有人说:函数调用是不是使得c++的程序复杂了,而且没有什么实际的用处呢?
恰恰相反,函数的使用让程序的可读性、可维护性更强。同时函数可以被反复调用,也提高了模块的可复用性。

例1:计算计算1/(1!+2!)+1/(2!+3!)...+1/(10!+11!)

不使用函数:
#include<iostream>

using namespace std;

//计算1/1!--1/10!
int main()
{
    double sum = 0;
    
    for(int i = 1; i <= 10; i++){
        double jc1 = 1, jc2 = 1;
        
        //计算i!
        for(int j = 1; j <= i; j++){
            jc1 *= j;
        }
        //计算i+1!
        for(int j = 1; j <= i+1; j++){
            jc2 *= j;
        }
        
        sum += 1.0 / (jc1+jc2);
    }
    cout << sum << endl;
    
    return 0;
}
使用函数:
#include<iostream>

using namespace std;

//计算n的阶乘
double jc(int n){
    double sum = 1;
    for(int i = 1; i <= n; i++){
        sum *= i;
    }
    return sum;
}

//计算1/1!--1/10!
int main()
{
    double sum = 0;

    for(int i = 1; i <= 10; i++){
        sum += 1.0 / (jc(i)+jc(i+1));
    }
    cout << sum << endl;

    return 0;
}

运行结果: 0.5

对比上面两段代码不难看出,使用函数的代码省去了重复编写求N!的部分,避免了重复而冗余的操作,比不使用函数的代码更易于让人理解,看起来更加清晰明了。

2.重载函数

定义:在相同的声明域中的函数名相同的,而参数表不同的,即通过函数的参数表而唯一标识并且来区分函数的一种特殊的函数。

使用重载的主要好处就是:不用为了对不同的参数类型或参数个数,而写多个函数。多个函数用同一个名字,但参数表,即参数的个数或(和)数据类型可以不同,调用的时候,虽然方法名字相同,但根据参数表可以自动调用对应的函数。

请看例2:

#include<iostream>

using namespace std;

int Max(int a, int b){
    return a > b ? a : b;
}

int Max(int a, int b, int c){
    if(a >= b && a >= c){
        return a;
    }else if(b >= a && b >= c){
        return b;
    }else if(c >= a && c >= b){
        return c;
    }
}


int main()
{
    cout << Max(1, 2) << endl;
    cout << Max(1, 2, 3) << endl;

    return 0;
}

运行结果:

2

3

例2中要求1,2中最大的一个数和1,2,3中最大的一个数,根据我们的经验,使用Max作为函数名是最好不过的了,但是若没有函数重载,我们会需要写一个Max2函数,一个Max3函数,太过麻烦。并且,若以后我们需要找出4个,5个或者更多数中最大的那一个数,我们还要去编写Max4,Max5,这样下来,程序设计会变得十分繁琐.

3.值传递和地址传递

我们先看一下百度上的解释:

按值传递:在过程被调用时,传递给形参的是调用过程中的相应实参的值,形参与实参各占有不同位置的储存空间,被调用过程在执行过程中,改变了形参变量的值,但不会调用过程的实参值。

按地址传递:就是当调用一个过程时,是把实参变量的内存地址传递给被调用过程的形参,也就是说形参与实参使用相同地址的内存单元。因此当在被调用过程中改变形参的值,就等于改变了实参的值。

具体的理解请看下面例子:

例三:
#include<iostream>

using namespace std;

void swap(int a, int a){
    int temp;
    temp = a;
    a = b;
    b = temp;
}

int main()
{
    int x = 1, y = 2;
    cout << "x = " << x << " y = " << y << endl;
    swap(x, y);
    cout << "x = " << x << " y = " << y << endl;

    return 0;
}

程序的运行结果为:

x = 1 y = 2

x = 1 y = 2

我们可能会想,为什么我将x,y的值传给了swap函数,并在函数内将他们的值交换,为什么最终打印的他们的值没变呢。原因是,我们函数传值的方式是用的值传递而不是地址传递。

我对值传递的理解就是,我们在swap函数中新定义了a,b变量,然后将main函数中的x,y的值拷贝给了函数中的a,b,我们只是在函数中交换了函数中a,b的值,并没有对main函数中的x,y值产生影响,并且,当函数结束后,a,b占用的内存也会被释放,即a,b不存在了。

下面我们看地址传递:

例4:
#include<iostream>

using namespace std;

void swap(int &a, int &b){
    int temp;
    temp = a;
    a = b;
    b = temp;
}

int main()
{
    int x = 1, y = 2;
    cout << "x = " << x << " y = " << y << endl;
    swap(x, y);
    cout << "x = " << x << " y = " << y << endl;

    return 0;
}

程序的运行结果为:

x = 1 y = 2

x = 2 y = 1

我们不难看出,两个例子的差别就在于swap函数的参数前加了两个&。

我对引用传递的理解为:传入函数的x,y就是main函数中的x,y,改变函数中的a,b的值也就是改变main函数中x,y的值,a,b相当于main函数中x,y的别名。

4.编写递归函数

递归函数的组成:终止条件和递归调用。

核心思想:不要纠结于递归的过程,把计算交给计算机去做,我们只需要最后的结果

下面是两个简单的递归函数的实现:

例5:编写递归函数计算1+2+...+n
#include<iostream>

using namespace std;

int fc(int n){
    if(n <= 1){
        return 1;
    }else{
        return n+fc(n-1);
    }
}

int main()
{
    int n;
    cin >> n;
    cout << "ans = " << fc(n) << endl;

    return 0;
}

运行结果:

输入: 10
输出: 55

例6:若f(1)=1,f(2)=2,f(n) = f(n-1)+f(n-2),求f(n)
#include<iostream>

using namespace std;

int f(int n){
    if(n == 1){
        return 1;
    }else if(n == 2){
        return 2;
    }
    else{
        return f(n-1)+f(n-2);
    }
}

int main()
{
    int n;
    cin >> n;
    cout << "f(n) = " << f(n) << endl;

    return 0;
}

运行结果:

输入:3

输出:3

注:由于以上程序的运行结果比较简单,为方便大家阅读,我就将程序的运行结果直接写出.

以上为我总结的C++函数部分的重要知识点,如有错误,敬请指正.

posted @ 2019-09-14 20:11  美团骑手阿霖  阅读(258)  评论(2编辑  收藏  举报