C/C++ 基础笔记(七)

本篇核心知识:函数基础、参数传递、函数重载、内联函数、函数指针、匿名函数、多文件编程、递归


一、函数基础(定义 / 调用 / 声明)

概念

函数是完成特定功能的代码块,可重复调用,提高代码复用性与可读性。

特性

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

    • 返回值:函数执行结果,void表示无返回值

    • 形参:定义时的占位参数,不可在定义时给默认参数;实参:调用时传入的真实值

    • 函数可以不含形参列表,即无参函数

  2. 函数声明:必须调用前声明,格式返回值类型 函数名(形参列表);,允许定义后置

    • 默认参数:仅写在声明中,从右往左赋值,不可重复定义

      例如:int fun(int,int=10) //带默认值的参数必须放在形参列表靠右位置

  3. 调用流程:

    1. 程序执行到调用处,转入被调函数

    2. 为形参分配临时内存,实参从左到右初始化形参

    3. 执行函数体,return带回结果并结束函数

    4. 回到主调函数继续执行,释放形参内存

  4. 全局变量与局部变量 :局部变量可以隐藏全局变量,在有同名全局变量和局部变量的情形时,可以用作用域解析运算符 ::提供对全局变量的访问。

    复制代码
    int a = 100;  // 全局变量a 
    void test() {    
        int a = 20; // 局部变量隐藏全局变量    
        cout << a << endl;      // 输出20,访问局部    
        cout << ::a << endl;    // 输出100,:: 访问全局 
    }
  5. 自定义函数内static定义的参数,不会随着多次调用被重新赋值

    int fac(int n){
    static int f=1; //static定义的int变量f,类似于函数范围内的全局变量
    f=f*n;
    return f;
    }
    main(){
    int i;
    for(i=1;i<=5;i++)
    printf("%d!=%d\n",i,fac(i));//输出1到5的阶乘(1!=1\n 2!=2\n 3!=6\n...... 5!=120\n)
    }

代码示例

复制代码
// 函数声明(含默认参数)
int add(int a, int b = 0);
​
// 函数定义
int add(int a, int b) {
    return a + b;
}
​
// 函数调用
int res = add(5); // b取默认值0,结果5

二、参数传递(三种方式)

概念

实参向形参传递数据的规则,决定函数内操作是否影响外部变量。

特性

1. 值传递(默认)
  • 特点:传递实参副本,修改形参不影响原变量

  • 适用:仅使用值、无需修改原数据

2. 地址传递(传指针)
  • 特点:传递变量地址,通过指针可修改原变量值

  • 适用:需修改外部变量、传递大数据

3. 引用传递(C++ 独有)
  • 概念:引用是变量别名,同一块内存空间

  • 特点:修改引用即改原变量,无需解引用

  • 定义:int &别名 = 原变量;,绑定后不可更改

4. 数组传参
  • 数组名传参自动退化为指针,丢失长度,需额外传长度参数

  • 函数内修改数组元素会影响外部原数组

代码示例

复制代码
// 值传递
void swap1(int a, int b) {
    int t = a; a = b; b = t;
}
​
// 地址传递
void swap2(int *a, int *b) {
    int t = *a; *a = *b; *b = t;
}
​
// 引用传递
void swap3(int &a, int &b) {
    int t = a; a = b; b = t;
}
​
// 数组传参
void printArr(int arr[], int len) {
    for(int i=0; i<len; i++) cout << arr[i] << " ";
}

相似概念比较:值传递 vs 地址传递 vs 引用传递

  • 值传递:副本隔离,安全不影响原值。

  • 地址传递:通过指针改原值,需解引用。

  • 引用传递:别名直接改原值,语法简洁(C++)。


三、函数重载(C++)

概念

同一作用域内,同名函数、参数列表不同,实现多态调用。

特性

  1. 区分依据:参数个数 / 类型 / 顺序返回值不参与区分

  2. 调用规则:按实参类型精确匹配

  3. 易错点:默认参数 + 重载易引发歧义,需避免

代码示例

复制代码
// 重载函数
int calc(int a) { return a * 2; }
int calc(int a, int b) { return a + b; }
double calc(double a) { return a * 3; }
​
// 调用匹配
cout << calc(5) << endl;    // 调用int calc(int)
cout << calc(2,3) << endl;  // 调用int calc(int,int)

四、内联函数(inline)

概念

C++中用inline修饰的函数,编译时直接展开函数体,减少调用开销。

特性

  1. 关键字:inline,声明 / 定义时均可加

  2. 原理:内存膨胀,空间换时间,避免函数跳转、栈帧创建开销

  3. 适用场景:短小、频繁调用的函数

  4. 限制:复杂函数(递归、循环多)不宜内联

代码示例

复制代码
// 内联函数
inline int square(int x) {
    return x * x;
}
​
// 调用时直接展开为x*x,无函数跳转
int s = square(4);

五、函数指针

概念

指向函数的指针,存储函数入口地址,可间接调用函数。

特性

  1. 定义格式:返回值类型 (*指针名)(参数类型列表);

  2. 调用方式:指针名(实参)(*指针名)(实参)

  3. 用途:回调函数、多态实现、函数数组

代码示例

复制代码
// 目标函数
int max(int a, int b) { return a > b ? a : b; }
​
// 定义函数指针
int (*pFun)(int, int) = max;
​
// 调用函数
cout << pFun(3,5) << endl; // 输出5

六、匿名函数(lambda表达式,C++11+)

概念

无需命名的临时函数,用于简单功能、捕获外部变量

(禁止在一个函数内定义另一个函数,因此在一个函数内可以通过匿名函数定义新的函数)

特性

  1. 格式:[捕获方式](参数)->返回值{函数体}

  2. 捕获方式:

    • [变量]:值捕获(只读)

    • [&变量]:引用捕获(可修改)

    • [=]:值捕获所有外部变量(只读)

    • [&]:引用捕获所有外部变量(可修改)

代码示例

复制代码
int main(){
    int x = 10;
    // 匿名函数:捕获x,传入a,输出x+a
    auto add = [x](int a) { return x + a; };
    cout << add(5) << endl; // 输出10 + 5
}

七、多文件编程

概念

将代码拆分到多个文件,便于维护、复用,由头文件(.h)和源文件(.cpp)组成。

特性

  1. 头文件(.h) :存放函数声明、宏、全局变量声明;用#pragma once防止重复定义

  2. 源文件(.cpp):存放函数实现、全局变量定义;包含对应头文件

  3. 规则 :全局变量仅定义一次,头文件只声明、不定义

代码示例

复制代码
// 头文件:fun.h
#pragma once
int add(int a, int b);

// 源文件:fun.cpp
#include "fun.h"
int add(int a, int b) {
    return a + b;
}

// 主文件:main.cpp
#include "fun.h"
int main() {
    cout << add(1,2) << endl;
    return 0;
}

八、递归

概念

函数直接或间接调用自身,解决重复性、分治类问题。

特性

  1. 两大要素:

    • 递归出口:结束条件,避免无限递归

    • 递归调用:向出口靠近,逐步简化问题

  2. 执行过程:层层深入调用,满足出口后逐层返回

  3. 适用场景:阶乘、斐波那契数列、扫雷翻开格子等

代码示例

复制代码
// 递归求阶乘
int factorial(int n) {
    if(n == 1) return 1; // 递归出口
    return n * factorial(n-1); // 递归调用
}

// 调用
cout << factorial(5) << endl; // 输出120
相关推荐
珊瑚里的鱼3 小时前
手撕单例模式中的饿汉模式和懒汉模式,懒汉模式还要再多加一个C++11版本的
开发语言·c++·单例模式
zh路西法3 小时前
【Linux 串口通信】基于 C++ 多线程的同步/异步串口实现
linux·运维·c++·python
不会C语言的男孩3 小时前
C++ Primer 第12章:动态内存
开发语言·c++
thisiszdy4 小时前
<C++> 浅拷贝与深拷贝
c++
2023自学中4 小时前
Linux虚拟机 CMakeLists.txt:x86 与 ARM 双架构编译脚本
linux·c语言·c++·嵌入式
眠りたいです4 小时前
现代C++:C++17中的新库特性
开发语言·c++·c++20·c++17
天若有情6735 小时前
【C++趣味实战】仿写Burp代理逻辑!自定义可控迭代器:拦截Intercept/放行Forward/重放Repeater全实现
java·开发语言·c++
磊 子5 小时前
C++function与bind绑定器讲解
java·jvm·c++
himobrinehacken5 小时前
C/C++中字符编码与指针应用全解析
c语言·逆向