C++---函数

时间:2020-05-09
本文章向大家介绍C++---函数,主要包括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;
}

参数按值传递

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

数组作为函数参数

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

一维数组作为参数

#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

参数的引用传递

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

使用引用参数

函数返回引用类型

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

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

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

  • 避免在设计函数中存在模糊的情况, 返回类型为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;
    }
    

原文地址:https://www.cnblogs.com/KX-Lau/p/12857587.html