当前位置: 首页 > 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.xdnf.cn/news/1068985.html

相关文章:

  • 基于STM32的个人健康助手的设计
  • ARM内核之CMSIS
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | BackgroundSlider(背景滑块)
  • Spring Boot中日志管理与异常处理
  • FPGA笔记——ZYNQ-7020运行PS端的USB 2.0端口作为硬盘
  • SpringBoot(九)--- HttpClient、Spring Cache、Spring Task、WebSocket
  • 鸿蒙OpenHarmony[Disassembler反汇编工具]ArkTS运编译工具链
  • Webpack 核心概念
  • ubuntu22.04可以执行sudo命令,但不在sudo组
  • 通俗易懂解读BPE分词算法实现
  • 【评估指标】IoU 交并比
  • 北斗导航 | 基于CNN-LSTM-PSO算法的接收机自主完好性监测算法
  • <六> k8s + promtail + loki + grafana初探
  • 14.Linux Docker
  • JavaScript逆向工程核心技术解密:反混淆、反调试与加密破解全景指南
  • 【cursor实战】分析python下并行、串行计算性能
  • 【网站内容安全检测】之1:获取网站所有链接sitemap数据
  • 鸿蒙与h5的交互
  • 机器学习01
  • IDEA高效开发指南:JRebel热部署
  • 每日AI资讯速递 | 2025-06-25
  • Django
  • (C++)vector数组相关基础用法(C++教程)(STL库基础教程)
  • 7.Spring框架
  • TensorFlow Lite (TFLite) 和 PyTorch Mobile模型介绍1
  • 什么是功能测试和非功能测试?
  • Azure 托管 Redis 已正式发布
  • 打造属于你的AI智能体,从数据开始 —— 使用 Bright Data MCP+Trae快速构建垂直智能体
  • 【Elasticsearch】es初识,在项目架构中的用途,与mysql和kafka的配合使用,
  • linux安装docker