zoukankan      html  css  js  c++  java
  • 读书笔记:C++ Primer系列(14)—— C++函数及参数传递

    一、函数

      实际项目中,要实现的功能不是仅靠一些基本语句就可以实现的,通常需要将这些大的功能进行分解,分步骤完成。例如:要实现一个学生信息管理系统, 一个学生信息管理系统至少包括学生信息的 添加查询删除修改等功能, 这些功能要求就是对该系统的初步分解, 然后以查询功能为例对其继续分解, 查询 功能可以再次分解为由以下几个功能组成的模块:

    • 获取用户查询信息;
    • 到数据库查询该学生信息;
    • 按照一定格式输出查询结果。

    如果感觉该功能实现起来还是比较困难那么就继续分解, 直到可以顺利实现。这些功能分解后的实现就是依靠函数, 函数在广义上理解为具有具体功能的一个模块, 在函数实现后, 通过对函数的调用来使用这个功能。

    1.函数声明

      函数声明也叫函数原型,包括返回类型、函数名、参数列表以及最后的一个分号。C++在处理函数调用之前,必须先看到该函数的声明或者定义。如果一个函数在不同源文件中被调用,那么每个源文件中都必须有声明。如果函数没有返回值,那么返回类型必须是void,如果什么都不写,默认返回类型是int。要避免不写返回类型

    2.函数定义

      函数包括返回类型、函数名、形参列表、花括号括起来的函数体。如果函数返回类型是void,return语句可有可无,如果有的话不要带任何参数。如果函数返回类型不是void,那么至少要有一个return,并且return后必须带一个值。函数定义在一个程序中只能出现一次,但是函数原型可以有多个。

      函数定义的格式为:
    返回值类型 函数名(参数列表)
    {
                函数体
     }

    例1: 

     int max(int a, int b)  //函数头

    {//函数体

        if(a>=b)

           return a;

        else

           return b;

    }

    二、函数的调用

      在任何的一个C++程序中, 都有一个被称为主函数的函数 - main(),该函数又被称为C++程序的入口函数,该函数的作用是告诉程序应该从这里开始执行指令, 也就是说,,任何一个C++程序都是从 main() 函数处开始执行, 直到执行过程中遇到程序的结束指令。

      C++中的函数之间可以互相调用,即:

                  main()函数可以调用任何函数,也包括自身;

                  自定义的函数可以调用其他自定义的函数或者库函数,自定义函数同样也可以调用main()函数。

    函数调用做了如下两件事:

    • 用对应的实参初始化函数的形参,并将控制权转移给被调用的函数;
    • 主调函数的执行被挂起,被调函数开始执行。

    每次调用函数时,该函数的所有形参都会被重新创建,此时将会用实参来初始化对应的形参。

    注:形参的初始化与变量初始化一样:如果形参是非引用类型,则复制实参的值;如果形参为引用类型,则它是实参的一个别名。  

    1. 非引用形参

    • 非引用类型的形参是通过复制对应的实参来实现初始化(实参副本来初始化形参)。
    • 非引用类型的形参实际上是对应实参的局部副本,对非引用类型的形参的修改仅仅改变了局部副本的值,一旦函数执行结束,这些局部变量的值也就随之没有了。

    例2: 

     void swap(int v1 , int v2)

    {
       int temp = v2;
       v2 = v1;
       v1 = temp;   
    }

     如果有函数调用swap(i, j),则i和j不受影响,只交换了副本的值。

    2. 指针形参

     当函数形参是指针时,此时将复制实参指针。与非引用形参一样,该类形参的任何改变也仅作用域局部副本。如果函数将新指针值赋给形参,主调函数的实参指针的值依然不会改变。

    例3:

    void add(int *p)

    {

         *p+=1;
           p+=1;


    上例中:使用指针做为函数的形参,同样指针的值(指针的地址)不会因为p+=1而受到影响,但是指针指向的地址的值(*p)将会改变。所以要想修改实参的值,可以使用这种方法。

    注意:       

    复制实参并不是适合所有情况,不适合采用复制实参的情况有:

    • 当需要在函数中修改实参的值时;
    • 当需要以大型对象作为实参传递时;
    • 当没有办法实现对象的复制时。

    3. 引用形参

    对于例1要实现的交换两个数的功能,需要将两个形参定义为引用类型才可以,即:

     例4:

    void swap(int &v1 , int &v2)

    {
       int temp = v2;
       v2 = v1;
       v1 = temp;   
    }

    每次被调用时,引用形参被创建并与相应的实参关联。当调用swap(i, j)时,形参v1只是实参对象i的另一个名字,而v2也只是实参对象j的另一个名字,对v1或v2的任何修改,实际上就是对i或j的修改。

    4.传递指向指针的引用

    例5:

    //修改指针指向的地址,而地址的值不变
    void fun(int *&v1,int *&v2)
    {
        int *p=v2;
        v2=v1;
        v1=p;
    }
    //交换指针指向地址的值
    void fun1(int *&v1,int *&v2)
    {
        int p=*v2;
        *v2=*v1;
        *v1=p;
    }
    int main()
    {
        int i=1;
        int j=2;
        int *v1=&i;
        int *v2=&j;
        cout<<"i="<<i<<" "<<"j="<<j<<endl;//1,2
        fun(v1,v2);
        cout<<"*v1="<<*v1<<" "<<"*v2="<<*v2<<endl;//2,1
        cout<<"i="<<i<<" "<<"j="<<j<<endl;//1,2 注意这里只是指针指向的地址交换,而i和j的值没变
        fun1(v1,v2);
        cout<<"i="<<i<<" "<<"j="<<j<<endl;//2,1 这里函数交换的是指针指向地址的值
        system("PAUSE");
        return 0;
    }

    上例中:
    int *&v1就是一个指向指针的引用,从右至左理解:v1是一个引用,与指向int类型对象的指针相关联,v1只是一个传递进函数的指针别名。 

     

  • 相关阅读:
    python计算机视觉项目实践
    Codeforces Round #256 (Div. 2) B (448B) Suffix Structures
    SonarLint插件的安装与使用
    后缀表达式求值
    有用代码段2
    提高Java代码质量的Eclipse插件之Checkstyle的使用具体解释
    Intellij Idea搭建Spark开发环境
    代码备忘, TODO宏实现
    浏览器自己主动填表安全漏洞:查看浏览器保存的password
    PDO 查询mysql返回字段整型变为String型解决方法
  • 原文地址:https://www.cnblogs.com/kkdd-2013/p/3714797.html
Copyright © 2011-2022 走看看