文章

函数指针

函数指针指向函数地址,可通过它调用函数,实现回调和动态绑定。

函数指针

函数指针

函数指针是 C++ 中一种保存函数地址的指针变量,允许像调用普通函数那样通过指针调用函数。它是理解回调机制、策略模式、以及 C/C++ 中函数灵活性的基础。

基本定义格式

1
返回类型 (*函数指针名)(参数类型列表);

示例:

1
2
3
4
5
6
7
8
9
10
11
12
int add(int a, int b) {
    return a + b;
}

// 定义函数指针
int (*funcPtr)(int, int);

// 把函数地址赋给指针
funcPtr = add;

// 通过指针调用函数
int result = funcPtr(3, 4);  // 结果是 7

经典用途

回调函数(如排序比较器):

1
2
3
4
5
6
7
8
9
10
bool cmp(int a, int b) {
    return a > b;
}

void sort(int* arr, int n, bool (*cmpFunc)(int, int)) {
    for (int i = 0; i < n - 1; ++i)
        for (int j = i + 1; j < n; ++j)
            if (!cmpFunc(arr[i], arr[j]))
                std::swap(arr[i], arr[j]);
}

调用:

1
2
int arr[] = {3, 1, 5, 2};
sort(arr, 4, cmp);  // 使用 cmp 作为比较器

简化语法(使用 typedefusing

  • 使用 typedef:
1
2
typedef int (*CalcFunc)(int, int);
CalcFunc f = add;
  • 使用 using(推荐):
1
2
using CalcFunc = int(*)(int, int);
CalcFunc f = add;

函数指针数组(策略表)

1
2
3
4
5
6
7
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }

using CalcFunc = int(*)(int, int);
CalcFunc ops[] = {add, sub};

int result = ops[0](10, 5);  // 调用 add,结果是 15

对比 lambda、std::function、虚函数指针

特性/维度函数指针Lambdastd::function虚函数指针(多态)
🧠 类型安全✅ 有✅ 有✅ 有✅ 有
📦 可捕获变量(闭包)❌ 不支持✅ 支持(捕获)✅ 支持捕获❌ 不支持
🔁 运行时可替换性✅/⚠️(无捕获)✅ 支持✅ 支持
🧮 调用开销(性能)🚀 极快(等同函数调用)🚀 极快(无捕获)🐢 慢些(封装、堆分配)🚀 快(虚表指针跳转)
🛠️ 存储/语法复杂度中(函数签名繁琐)简洁简洁中(需要类定义)
🧩 可用于类成员⚠️ 不能直接✅ 可✅ 可✅ 虚函数
♻️ 可用于策略/回调✅ 是✅ 是✅ 是✅ 是
🧱 是否编译期可求值❌ 否⚠️ 无捕获可以❌ 否❌ 否

函数指针(最古老也最快)

1
2
3
int add(int a, int b) { return a + b; }
int (*fptr)(int, int) = add;
fptr(3, 4); // 结果 7
  • 优点:开销低、语义清晰
  • 缺点:不能绑定状态、不支持捕获、不支持类成员函数

Lambda 表达式

1
2
3
4
5
auto f = [](int a, int b) { return a + b; };
f(3, 4); // 结果 7

int x = 10;
auto g = [x](int y) { return x + y; }; // 捕获外部变量
  • 有状态时是类对象(编译器生成),不能隐式转函数指针
  • 无捕获时可以自动转成函数指针

std::function(泛型可调用封装器)

1
2
3
4
5
6
#include <functional>

std::function<int(int, int)> f = [](int a, int b) {
    return a + b;
};
f(3, 4); // 结果 7
  • 支持 lambda(有/无捕获)、函数指针、成员函数、仿函数
  • 内部封装复杂类型,易用但可能有堆内存开销
  • 推荐用于高抽象、插件系统、通用回调接口

虚函数指针(多态)

1
2
3
4
5
6
7
8
9
10
class Strategy {
public:
    virtual int apply(int a, int b) = 0;
    virtual ~Strategy() = default;
};

class Add : public Strategy {
public:
    int apply(int a, int b) override { return a + b; }
};
  • 支持接口多态(运行时绑定)
  • 类中通过虚函数表调用,支持成员状态
  • 有轻微开销(虚表指针跳转),但是面向对象设计核心
场景推荐方案理由
高性能、无状态策略(如 sort)✅ 函数指针 / 无捕获 Lambda快,简单
动态策略,有捕获std::function支持闭包
面向对象策略,多态结构✅ 虚函数扩展性强
编译期策略✅ 模板 / constexpr 函数编译时计算
小工具函数 / callback✅ Lambda简洁、现代
本文由作者按照 CC BY 4.0 进行授权