当前位置: 首页 > news >正文

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 是更现代更通用的可调用包装器
http://www.jsqmd.com/news/723677/

相关文章:

  • 数据知识驱动光网络故障诊断【附代码】
  • 为什么制造业花了很多钱做营销,AI搜索还是引用不到你?
  • 海康云眸Claw:以“数字员工”重塑零售连锁管理,提质增效降本!
  • 工业计算机在机床上下料机器人中的应用与产品解决方案
  • 基于MATLAB Simulink仿真的21电平MMC整流站与逆变站两端柔性互联技术研究
  • 微信聊天记录永久保存完全指南:WeChatMsg三步导出你的数字记忆
  • 用肌电信号和形状记忆聚合物,我复现了一款能抓手机的软体机器人手(附开源代码)
  • 告别SE93!SAP顾问必看:用参数型事务码关联QUERY报表的保姆级教程
  • 注册表,项,值,数据,微软这套命名完全反人类
  • AI Agent框架探秘:拆解 OpenHands()--- Runtime
  • 【ImportError: libGL.so.1】
  • 提升GitLab代码质量分析效率的妙招
  • 德国联邦议院拟用 Wire 取代 Signal,迈向数字主权新征程
  • 【西瓜带你学Kafka | 第二期】深度解析Kafka的分区机制与高效存储设计原理(文含图解)
  • 冷钱包选购的安全标准答案:锁定Ledger官方授权店铺
  • FPGA ASIC IP解密服务,助力获取加密源码与Vivado2021等解决方案
  • Fan Control终极指南:三步告别电脑噪音烦恼,打造个性化散热方案
  • 基于51单片机智能恒温杯垫温度检测控制系统设计17-304
  • 2026年Gemini办公应用实测:5个真实场景效率提升记录
  • 2026年苹果iOS 27等系统“照片”应用将推AI编辑工具,部分功能或推迟
  • 从公式到代码:手把手教你推导并实现微带线特性阻抗的Matlab计算模型
  • 阿里云国际站代理商(云老大):阿里云国际站无影云电脑使用指南
  • DMP侧信道攻击防御:SplittingSecrets技术解析
  • CoinGlass API 好用吗?(2026深度评估)
  • GitHub第1299号用户带5万星项目出逃,AI重压下GitHub何去何从?
  • 高德、百度、腾讯地图API混用?一份讲透国内主流坐标系差异与选型避坑指南
  • 2026年四川山特代理TOP5盘点:性价比与服务双维度对比 - 优质品牌商家
  • ComfyUI IPAdapter Plus完整指南:AI图像风格迁移的终极解决方案
  • 【Linux从入门到精通】第31篇:防火墙漫谈——iptables与firewalld防护指南
  • 知识图谱与LLM融合:GraphRAG工程实践2026