• C++---函数


    函数

    • 函数三要素: 返回值类型, 函数名, 参数列表
    int sum(int, int); //函数声明
    
    int main()
    {
        //函数调用
        int result = sum(5, 3);
    }
    
    //函数定义
    int sum(int num1, int num2)
    {
        //函数实现的代码
    }
    
    • 函数声明与函数定义的头部类型, 最后以分号结尾
    • 函数声明中的参数名称可以省略, 只写参数类型
    • C++中返回值类型不能是数组, 但是可以是其他任何类型, 可以将数组作为结构或者对象组成部分返回
    #include <iostream>
    
    using namespace std;
    
    double cuboidV(double, double, double);
    
    int main()
    {
        cout << cuboidV(15.1, 12, 11.5);
        return 0;
    }
    
    //长方体体积
    double cuboidV(double length, double width, double height)
    {
        return length * width * height;
    }
    
    

    参数按值传递

    • 给函数传递参数时, 参数不会直接传递给函数, 而是先制作参数的副本, 存储在栈上, 再使用这个副本用于函数, 而不是使用初始值.

      image-20200502220557809

    数组作为函数参数

    • 数组作为函数实参时, 只传递数组的地址(首地址), 并不传递整个数组的空间
    • 当用数组名作为实参调用函数时, 数组首地址指针就被传递到函数中

    一维数组作为参数

    #include <iostream>
    
    using namespace std;
    
    
    //函数声明
    void print(const int *, int);
    
    int main(){
        int values[]{100, 120, 80, 90};
        //函数调用, 数组作为实参, 只传递地址
        print(values, 4);
    }
    
    //函数实现, const修饰参数, 防止参数在函数内被修改
    void print(const int values[], int len)
    {
        string value_names[]{"体力", "智力", "魅力", "气质"};
        for(int i = 0; i < len; i++){
            cout << value_names[i] << ":" << values[i] <<endl;
        }
    }
    

    二维数组作为参数

    #include <iostream>
    
    using namespace std;
    
    //函数声明
    void show(const double (*)[5], int);
    
    int main()
    {
        double powers[3][5]{
            {45.5, 55.6, 88.9, 66.6, 78},
            {98.2, 69.1, 33.7, 49.3, 58},
            {78.2, 58.6, 12.8, 37.8, 43},
        };
        //函数调用
        show(powers, 3);
    
    }
    
    //函数实现
    void show(const double arrays[][5], int len)
    //void show(const double (*arrays)[5], int len)
    {
        for(int i = 0; i < len; i++){
            for (int j = 0; j < 5; j++){
                cout << arrays[i][j] << ', ';
            }
            cout << endl;
        }
    
    }
    

    函数指针

    • 函数也有地址, 函数的地址是存储其机器语言代码的内存开始地址
    • 好处: 可以在不同的时间使用不同的函数
    //函数指针的声明
    double (*ptr_sum)(double, double);  //该语句声明了一个指针ptr_sum, 指向一个函数
    
    double* ptr_sum(double, double);   //不是函数指针, 而是声明了一个函数ptr_num, 返回值是double*类型
    

    函数的进阶

    内联函数

    • 内联函数是C++为提高程序运行速度所做的一项改进

    • 与常规函数的区别不在于编写方式, 而是编译器使用函数代码替换函数调用

    • 如果执行函数代码的时间比处理函数调用机制的时间长, 则节省的时间将只占整个过程的很小一部分

    • 如果代码执行时间很短, 内联调用就可以节省大部分时间

    • 使用内联特性, 在函数声明前加关键字inline 或 在函数定义前加关键字inline

      image-20200503111526120

    参数的引用传递

    • 引用是给对象起的另外一个名字, 引用即别名
    • 引用并对象, 只是为一个已经存在的对象起的别名
    • 引用必须初始化
    • 引用更接近与const, 一旦与某个变量关联起来, 就将一直效忠于它
    • 将引用变量用作参数时, 函数将使用原始数据, 而不是副本
    • 当数据所占内存比较大时, 建议使用引用参数

    使用引用参数

    image-20200503111845583

    函数返回引用类型

    • 不要返回局部变量的引用, 局部变量的生存期只在函数中. 函数中的局部变量会被内存回收, 你程序中申请的这块内存已经不是你的了!

    • 函数可以不返回值, 默认返回最后一个对象的引用

    • 返回引用时, 要求函数参数中包含被返回的引用对象

    • 避免在设计函数中存在模糊的情况, 返回类型为const int&, const类型为不可修改的左值

      const int& sum(int & num){
          
      }
      
      int num = 10;
      int& result = sum(num);
      sum(num) = 55;                //加const之后不合法
      

    小结

    • 能够修改调用函数中的数据对象
    • 数据对象较大时传递引用可以提高程序的运行效率
    • 函数中不需要修改传递的参数
      • 如果数据很小, 建议按值传递
      • 传递数组只能使用指针, 并使用const关键字
      • 较大的对象则使用const指针或引用
    • 函数中需要修改传递的参数
      • 数据对象是基本类型或结构时, 可以使用指针或引用
      • 数据对象是数组时只能使用指针
      • 数组对象是类对象时, 建议使用引用

    默认参数

    • 默认值可以在函数声明或定义中给出, 不能在两个位置同时出现

    • 带参数列表的函数, 必须从右向左添加默认值

      void test1(int a, int b = 5, int c = 10);
      void test2(int a, int b = 5, int c);            //不合法, 默认参数后的参数也需有默认值
      void test1(int a = 1, int b = 5, int c = 10);
      

    函数重载

    • 可以有多个同名的函数

    • 函数名相同, 但是参数列表不同, 即特征标不同

      //编译器在编译时, 根据参数列表对函数进行重命名
      void eating();
      void eating(string);   
      void eating(string[]);
      void eating(int, int, int);    eating_int_int_int
      
      void eating(string&);  //和eating(string)的特征标识相同的, 编译器把类型引用和类型本身视为同一个特征标
      

    函数模板

    • 函数模板就是建议一个通用函数

    • 函数定义时不指定具体的数据类型, 使用虚拟类型代替

    • 函数被调用时编译器根据实参反推数据类型, 类型的参数化

      //函数声明
      template<typename T> void Swap(T&, T&);
      
      //模板头
      template<typename T>
      void Swap(T& a, T& b)
      {
          T temp = a;
          a = b;
          b = temp;
      }
      
  • 相关阅读:
    js中break/continue
    js实现连接的两种放法
    jsdate对象toLocaleString()方法小结
    接口学习小节
    c# 装箱和拆箱
    c#数据类型学习
    return 作用域
    js中break/continue
    ArcGIS Runtime for Android开发教程V2.0(9)基础篇查询检索
    【转】ArcGIS 10.1 地图发布以及缓存管理
  • 原文地址:https://www.cnblogs.com/KX-Lau/p/12857587.html
Copyright © 2020-2023  润新知