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

【C++】std::function是什么

std::function是C++11引入的一个模板类,它可以看作是一个"万能函数容器",能够存储、复制和调用几乎任何可调用的目标(函数、lambda表达式、函数对象等)。

一、std::function是什么?

  • 想象你有一个神奇的盒子(std::function),这个盒子可以装下:
  • 普通函数
  • 类的成员函数
  • lambda表达式
  • 函数对象(重载了operator()的类)
    这个盒子不仅能保存这些可调用对象,还能像普通函数一样使用它们。

二、std::function的基本用法

  1. 基本语法
#include <iostream>
#include <functional>// 普通函数
int add(int a, int b) {return a + b;
}int main() {// 创建一个可以存储"接受两个int参数,返回int"的函数的包装器std::function<int(int, int)> func;// 存储普通函数func = add;std::cout << func(2, 3) << std::endl;  // 输出5// 存储lambda表达式func = [](int a, int b) { return a * b; };std::cout << func(2, 3) << std::endl;  // 输出6return 0;
}

三、std::function的作用

​统一接口​:可以用相同的方式调用不同类型的可调用对象
​延迟执行​:先保存函数,稍后再调用
​回调机制​:常用于事件处理、观察者模式等场景
​运行时多态​:可以在运行时决定调用哪个函数

1. 设置lambda函数为回调函数

#include <functional>
#include <vector>class Button {std::function<void()> onClick;
public:void setOnClick(std::function<void()> callback) {onClick = callback;}void click() {if(onClick) onClick();  // 如果有回调函数就调用}
};int main() {Button btn;// 设置lambda作为回调btn.setOnClick([]() {std::cout << "按钮被点击了!" << std::endl;});btn.click();  // 输出"按钮被点击了!"return 0;
}

2. 策略模式

#include <functional>
#include <vector>class Sorter {std::function<bool(int, int)> compare;
public:void setCompare(std::function<bool(int, int)> cmp) {compare = cmp;}void sort(std::vector<int>& nums) {if(compare) {// 使用设置的比较函数排序std::sort(nums.begin(), nums.end(), compare);} else {// 默认排序std::sort(nums.begin(), nums.end());}}
};int main() {Sorter sorter;std::vector<int> nums = {3, 1, 4, 1, 5, 9, 2, 6};// 设置升序排序策略sorter.setCompare([](int a, int b) { return a < b; });sorter.sort(nums);// 设置降序排序策略sorter.setCompare([](int a, int b) { return a > b; });sorter.sort(nums);return 0;
}

3. 存储成员函数

#include <functional>class Calculator {
public:int multiply(int a, int b) {return a * b;}
};int main() {Calculator calc;// 存储成员函数需要绑定对象实例std::function<int(int, int)> func = std::bind(&Calculator::multiply, &calc, std::placeholders::_1, std::placeholders::_2);std::cout << func(3, 4) << std::endl;  // 输出12return 0;
}

四、总结

​什么时候使用std::function?​​

  • 当你需要存储不同类型的可调用对象时
  • 当你需要在运行时决定调用哪个函数时
  • 当你需要实现回调机制时
  • 当你需要统一函数接口时

疑问

1. 为什么回调函数常用Lambda而非普通函数

void processOrder(const std::string& dish) {int priority = getCurrentPriority();  // 获取当前优先级// Lambda可以"记住"当前priority的值kitchen.notify([priority, &dish]() {std::cout << "制作" << dish << " (优先级:" << priority << ")";});
}
  • 普通函数无法直接访问局部变量priority
  • ​Lambda可以捕获当前作用域的变量,形成闭包
  • Lambda把逻辑放在使用的地方,减少跳转
  • 特别适合简单的一次性操作
  • 如果使用函数指针作为回调函数的形参,那么传入lambda表达式的时候不能有捕获参数;如果lambda有捕获参数,想要作为形参传给回调函数,就只能使用std::function进行封装。

2. 虽然Lambda很强大,但普通函数仍有其用途

  • 复杂逻辑​:当回调逻辑很复杂时,单独的函数更易维护
  • 需要重用时​:多个地方调用相同逻辑时
  • C接口兼容​:需要转换为函数指针时
http://www.lryc.cn/news/575303.html

相关文章:

  • 【网络实验】-配置用户登录
  • 《高等数学》(同济大学·第7版)第九章 多元函数微分法及其应用第一节多元函数的基本概念
  • ARM内核之CMSIS
  • 《从0到1:C/C++音视频开发自学完全指南》
  • 超级好用的小软件:geek,卸载软件,2m大小
  • HarmonyOS 5分布式数据库有哪些性能指标?
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | BackgroundSlider(背景滑块)
  • 【Docker基础】Docker容器管理:docker pause、stop、kill区别
  • Windows下安装zookeeper
  • 【nRF52832】【环境搭建 1】【ubuntu下搭建nRF52832开发环境】
  • 一篇文章了解XML
  • 20250625解决在Ubuntu20.04.6LTS下编译RK3588的Android14出现cfg80211.ko的overriding问题
  • 【DataWhale组队学习】AI办公实践与应用-数据分析
  • 《仿盒马》app开发技术分享-- 待发货兑换订单列表(76)
  • 使用EasyExcel处理动态表头数据导入
  • Aurora MySQL 3.05/3.06/3.07版本即将停用,全局数据库升级实战指南
  • 鸿蒙ArkUI---基础组件Tabs(Tabbar)
  • 日本生活:日语语言学校-日语作文-沟通无国界(5)-题目:我的一天
  • Boss:攻击
  • ChaCha20加密解密技术
  • 使用 Netty 实现 TCP 私有协议(解决粘包/拆包)
  • 三步实现B站缓存视频转MP4格式
  • WeakAuras Lua Script [ICC BOSS 12 - The Lich King]
  • 【笔记——李沐动手学深度学习】2.3 线性代数
  • PyTorch RNN实战:快速上手教程
  • MySQL之存储过程详解
  • IoT/HCIP实验-5/基于NB-IoT的智慧农业实验(平台侧开发+端侧编码+基础调试分析)
  • 重置 MySQL root 密码
  • python接口测试参数multipart/form-data格式不能有多余的空格或 tab 缩进
  • 计算机网络-----详解HTTPS协议