C++函数指针与 std::function 学习笔记
前言
学习 C++ 时,很多人第一次看到下面代码都会懵:
void (*p)();甚至看到现代 C++:
function<void()> cb;更像天书。
但其实它们本质都在做一件事:
把函数当作参数传递 或者保存起来再调用这也是回调函数、Qt信号槽、lambda 的基础。
这篇系统梳理:
什么是函数指针
如何理解函数指针语法
std::function是什么
两者区别
回调应用
一、函数也有地址
变量有地址:
int a=10;有:
&a函数其实也有地址。
例如:
#include<iostream> using namespace std; void hello() { cout<<"hello"<<endl; }函数:
hello本质可以看成函数入口地址。
二、什么是函数指针
普通指针
int x=10; int* p=&x;p 存变量地址。
函数指针
void (*p)();表示:
p 是一个指针 指向函数这个函数:
返回 void
参数为空
拆开理解
void (*p)();先看:
(*p)说明:
p是指针void说明:
返回值:
void()说明:
没有参数。
合起来:
指向 void() 函数的指针三、函数指针使用
#include<iostream> using namespace std; void hello() { cout<<"hello"<<endl; } int main() { void (*p)();//创建函数指针 p = hello;//指向对应类型的函数hello p();//调用 }输出:
hello相当于:
p();就是:
hello();四、带参数函数指针
函数:
int add(int a,int b) { return a+b; }对应函数指针:
int (*p)(int,int);使用:
p=add; cout<<p(3,5);输出:
8五、为什么必须写 (*p)
很多人会写错:
int *p();这不是函数指针。
这是:
返回int* 的函数真正函数指针:
int (*p)();括号不能少。
六、函数指针做回调
#include<iostream> using namespace std; void callback() { cout<<"回调执行"<<endl; } void work(void (*p)()) { cout<<"工作中"<<endl; p(); } int main() { work(callback); }输出:
工作中 回调执行这就是回调。
七、什么是 std::function
现代 C++ 更常用:
function<void()> cb;头文件:
#include<functional>语法格式
function<返回类型(参数列表)>例如:
function<void()>表示:
一个可调用对象 签名是 void()八、使用 std::function
#include<iostream> #include<functional> using namespace std; void hello() { cout<<"hello"<<endl; } int main() { function<void()> cb; cb=hello; cb(); }输出:
hello九、它比函数指针强在哪
函数指针:
只能存普通函数std::function 能存:
普通函数
lambda
成员函数
仿函数
很灵活。
十、lambda 配合 function
function<void()> cb= []() { cout<<"lambda执行"<<endl; }; cb();输出:
lambda执行十一、函数指针 vs std::function
| 对比 | 函数指针 | std::function |
|---|---|---|
| 写法 | 复杂 | 简单 |
| 功能 | 普通函数 | 各种可调用对象 |
| 灵活性 | 低 | 高 |
| 现代项目 | 少 | 多 |
| 推荐度 | 了解原理 | 实际常用 |
老式写法
void (*p)();现代写法
function<void()> cb;更推荐。
十二、完整回调示例(现代写法)
#include<iostream> #include<functional> using namespace std; void work(function<void()> cb) { cout<<"处理任务"<<endl; cb(); } int main() { work([](){ cout<<"回调执行"<<endl; }); }输出:
处理任务 回调执行十三、什么时候用哪个
如果是理解底层:
学函数指针写现代项目:
优先 std::function工业界常见组合:
function + lambda十四、总结
函数指针本质:
用指针保存函数地址经典写法:
void (*p)();现代替代:
function<void()>更灵活。
口诀记忆:
函数地址能保存 函数指针可回调 现代推荐function lambda配合更灵活⭐⭐⭐⭐⭐⭐⭐⭐
函数指针保存函数地址实现回调 std::function 是更现代更通用的可调用包装器