0

0

c++中如何使用std::function_c++通用函数包装器用法详解【实例】

穿越時空

穿越時空

发布时间:2026-01-25 10:43:37

|

189人浏览过

|

来源于php中文网

原创

std::function 是可调用对象的类型擦除容器,非万能函数指针;支持函数指针、lambda、bind 等,但有开销、不可比较、移动后状态未定义。

c++中如何使用std::function_c++通用函数包装器用法详解【实例】

直接说结论:std::function 不是“万能函数指针”,它本质是可调用对象的类型擦除容器,能存函数指针、lambda、绑定表达式、成员函数指针等,但有开销、不能比较相等、不支持移动后状态检查。

std::function 的声明与基本赋值场景

声明时必须显式指定签名,比如 std::function 表示接受两个 int 参数、返回 int 的可调用对象。常见错误是漏写括号或参数类型不匹配:

  • 错:std::function f = [](int a, int b) { return a + b; }; —— 这行其实对,但若 lambda 捕获了局部变量而没加 [&][=],编译失败
  • 错:std::function f = some_function_ptr;some_function_ptr 实际是 void(*)(int) —— 签名不兼容,直接编译报错
  • 正确赋值来源包括:普通函数指针无捕获 lambda(自动转为函数指针)std::bind 结果、std::mem_fn 或成员函数指针包装体

捕获型 lambda 和 std::function 的内存开销

std::function 内部用小对象优化(SOO),通常前 16–32 字节存在自身对象里;一旦 lambda 捕获大量数据(如大数组、std::stringstd::vector),就会触发堆分配。这不是 bug,但容易被忽略:

  • 小捕获(如 [x](int y){ return x + y; },其中 xint)—— 通常不堆分配
  • 大捕获(如 [data = std::vector(100000)](){ ... })—— 必然堆分配,且拷贝构造 std::function 会复制整个 vector
  • 避免方式:改用引用捕获 [&data](注意生命周期!),或把大数据抽成外部对象,只捕获指针/引用
std::vector big_data(100000, 42);
auto bad_lambda = [big_data]() { return big_data.size(); }; // 堆分配,拷贝重
auto good_lambda = [&big_data]() { return big_data.size(); }; // 不复制 data,但需确保 big_data 活得比 function 久
std::function f = good_lambda;

std::function 与成员函数指针的绑定

不能直接把成员函数指针赋给 std::function,因为缺少 this。必须绑定实例(或用 std::bind / lambda 包装):

动态WEB网站中的PHP和MySQL:直观的QuickPro指南第2版
动态WEB网站中的PHP和MySQL:直观的QuickPro指南第2版

动态WEB网站中的PHP和MySQL详细反映实际程序的需求,仔细地探讨外部数据的验证(例如信用卡卡号的格式)、用户登录以及如何使用模板建立网页的标准外观。动态WEB网站中的PHP和MySQL的内容不仅仅是这些。书中还提到如何串联JavaScript与PHP让用户操作时更快、更方便。还有正确处理用户输入错误的方法,让网站看起来更专业。另外还引入大量来自PEAR外挂函数库的强大功能,对常用的、强大的包

下载

立即学习C++免费学习笔记(深入)”;

  • 错:std::function f = &MyClass::do_something; —— 编译失败,“no known conversion”
  • 对(lambda):MyClass obj; std::function f = [&obj]() { obj.do_something(); };
  • 对(std::bind):std::function f = std::bind(&MyClass::do_something, &obj);
  • 注意:若用 std::bind 绑定临时对象(如 std::bind(..., MyClass{})),调用时 this 悬空,UB

性能敏感场景下 std::function 的替代选择

如果函数调用在 hot path(如循环内、图形渲染每帧调用),std::function 的虚函数调用开销(即使 SOO)和可能的堆访问会影响性能。这时应考虑:

  • 模板参数化:把可调用对象作为模板参数传入,让编译器内联(最高效)
  • 函数指针:仅限无状态、无捕获的自由函数
  • 手动函子(functor)类:定义 operator(),零开销,但失去类型擦除能力
  • 别为了“统一接口”强行用 std::function —— 它的便利性是有代价的

真正麻烦的不是怎么写,而是忘记它背后是类型擦除+运行时分发,以及移动后原对象进入有效但未指定状态(不能再次调用,也不能比较)。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

381

2023.08.02

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

381

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

542

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

53

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

176

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

98

2025.11.27

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.15

c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

25

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.2万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号