C 语言学习五:函数与程序结构

函数与程序结构

  • 函数的声明与定义
    • 函数的声明
    • 函数的定义
    • 函数重载
    • 内联函数
    • 递归函数
    • 构造函数
    • lambda 函数
  • 函数的参数
    • 形参和实参
    • 值传递和引用传递
    • 默认参数
  • 函数的返回
    • 返回多个值
    • 返回引用
    • 返回指针
    • 返回对象
  • 头文件
  • 内部函数和外部函数
    • 内部函数
    • 外部函数

函数的声明与定义

函数的声明

  1. 使用函数之前,需要提供函数的声明。声明告诉编译器有一个函数存在,但不提供具体的实现
  2. 通常在头文件(.h)中进行函数声明,以便在多个文件中共享函数接口
  3. 函数声明包括函数的返回类型、函数名、参数列表(参数类型和参数名),但不包括函数体
    // 函数声明
    int add(int a, int b);
    

函数的定义

就是cpp里的函数的具体实现

// 函数定义
int add(int a, int b) {
    return a + b;
}

函数重载

C++允许在同一作用域中声明多个具有相同名称但参数列表不同的函数

// 函数重载
int add(int a, int b);
double add(double a, double b);

内联函数

  • 什么是内联函数?——参考文章
  • 使用场景:
    内联函数通常用于需要频繁调用、函数体较小且性能敏感的情况。它是一种编译器的优化手段,可以提高程序的执行效率。内联函数的使用场景包括但不限于:
    小型函数体: 内联函数适用于函数体较小的情况,因为内联函数会将函数体的代码插入到每次调用的地方,如果函数体较大,内联可能会导致代码膨胀,影响性能。
    频繁调用的函数: 内联函数适用于频繁调用的函数,因为函数调用本身会有一些开销,内联可以减少这种开销。
    性能敏感的代码: 内联函数适用于对性能要求较高的代码段,因为它可以减少函数调用的开销,提高执行速度。
  • 内联函数是在编译时期处理的,而不是在预处理时期。在编译时,编译器会根据函数的声明和定义,在每次调用的地方插入函数体的代码,而不是像普通函数一样生成一个独立的函数调用。这样可以减少函数调用的开销,但也会增加代码的体积。因此,内联函数的使用需要谨慎,最好在性能分析的基础上进行决策。

递归函数

递归函数是调用自身的函数。递归函数需要有一个终止条件,否则将无限循环

// 递归函数
int factorial(int n) {
    if (n <= 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

构造函数

  • 语法:类名(){}
  1. 构造函数,没有返回值也不写void
  2. 函数名称与类名相同
  3. 构造函数可以有参数,因此可以发生重载
  4. 程序在调用对象时候会自动调用构造,无须手动调用,而且只会调用一次

lambda 函数

[capture](parameters) -> return_type {
    // 函数体
}
  • capture:捕获列表,用于在 lambda 函数中引用外部变量。捕获列表可以为空,也可以包含变量名、变量列表,或者通过引用捕获。
    parameters:参数列表,与普通函数的参数列表相似,但可以为空。
    -> return_type:返回类型声明,可以省略,编译器会自动推导返回类型。
    {}:函数体
#include 
int main() {
    // Lambda 表达式,将两个数相加
    auto add = [](int a, int b) -> int {	//auto 用于自动推导变量的类型
        return a + b;
    };
    // 使用 Lambda 函数
    int result = add(3, 4);
    std::cout << "The sum is: " << result << std::endl;
    return 0;
}

函数的参数

形参和实参

  • 形参
    1. 形参是函数定义中声明的变量,用于接收调用该函数时传递的实参
    2. 形参在函数定义的括号内声明,它们是函数体内的局部变量,只在函数内部可见
    3. 形参的作用是充当函数内部的占位符,用于处理传递给函数的实际数据
    void exampleFunction(int parameter1, float parameter2) {
        // function body
    }
    
  • 实参
    1. 实参是函数调用时传递给函数的具体数值或变量
    2. 实参与形参一一对应,按顺序传递给函数。实参的值被赋给对应位置的形参
    3. 实参可以是常量、变量、表达式等
    int main() {
        int a = 10;
        float b = 3.14;
        // 调用函数并传递实参
        exampleFunction(a, b);
        return 0;
    }
    

值传递和引用传递

  1. 值传递是指将实参的值复制给形参,在函数内部对形参的修改不影响实参
  2. 引用传递是通过传递实参的引用,使函数能够直接操作实参的值
    #include 
    void byReference(int& x) {
        x = x * 2;
    }
    void byValue(int x) {
        x = x * 2;
    }
    int main(int argc, char** argv)
    {
        int a=2,b=2;
        byValue(a);
        byReference(b);
        printf("a=%d\n", a);
        printf("b=%d\n", b);
    }
    //结果为a=2;b=4
    

默认参数

默认参数是在函数声明中为形参设置默认值,如果调用函数时没有提供对应实参,将使用默认值

// 函数声明,其中 b 的默认值为 10
void exampleFunction(int a, int b = 10);
// 函数定义
void exampleFunction(int a, int b) {
    // 函数体
}

函数的返回

返回多个值

可以使用结构体、数组或类等方式实现函数返回多个值的效果

struct Point {
    int x, y;
};
Point getCoordinates() {
    Point p;
    p.x = 10;
    p.y = 20;
    return p;
}

返回引用

#include 
int x = 5;
int& getVariable() {
    return x;
}
int main(int argc, char** argv)
{
    getVariable() = 10;
    printf("x的值为:%d\n", x); // x 现在的值是 10
    return 0;
}

返回指针

函数可以返回指针,通常用于返回动态分配的内存

int* createInt() {		//返回一个指向整数的指针 (int*)
    int* ptr = new int;	//使用 new 运算符在堆上动态分配了一个新的整数。这个新分配的内存的地址被存储在指针变量 ptr 中
    *ptr = 42;	//设置了这个内存位置的值
    return ptr;
    //return *ptr;如果这样写就是返回int型
}

返回对象

通常用于实现链式调用(也叫流式接口)
在 C++ 中,& 符号用于声明引用

#include 
struct MathOperations {
    int value;
    MathOperations& add(int x) {
        value += x;
        return *this;
    }
    MathOperations& multiply(int x) {
        value *= x;
        return *this;
    }
};
int main() {
    MathOperations result{5};   //value 成员初始化为 5
    result.add(3).multiply(2);
    std::cout << "Result: " << result.value << std::endl;  // 输出:Result: 16
    return 0;
}
  • return this与return *this区别
    参考文章
    return *this返回的是当前对象的克隆或者本身(若返回类型为A, 则是克隆, 若返回类型为A&, 则是本身 )。return this返回当前对象的地址(指向当前对象的指针)

头文件

  • 头文件保护
    头文件保护(也称为 include guard 或防卫式声明)是一种防止头文件被多次包含的机制。通过#ifndef、#define、#endif 来实现
    // 头文件保护示例
    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    // 头文件内容
    #endif
    
  • 内联函数
    通常直接放在头文件中,以便在编译时进行函数体的替换,提高性能
    // 内联函数示例
    #ifndef EXAMPLE_H
    #define EXAMPLE_H
    
    inline int add(int a, int b) {
        return a + b;
    }
    #endif
    

内部函数和外部函数

内部函数

  • 内部函数是在另一个函数内部定义的函数
    内部函数的作用域限定在外部函数中,无法在外部函数以外的地方调用
    内部函数通常用于封装和隐藏实现细节
void outerFunction() {
    // 内部函数
    void innerFunction() {
        // 内部函数的实现
    }
    // 调用内部函数
    innerFunction();
}

外部函数

  • 默认情况下,函数(除了静态函数和内部函数)具有外部链接性,可以在其他文件中调用
  • 外部函数的声明通常放在头文件中,以便在多文件项目中共享函数接口。

你可能感兴趣的:(c语言,学习,开发语言,c++)