函数指针、函数符与Lambda表达式
先来看这样一段代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <iterator>
int main()
{
std::vector<int> v(500);
std::generate(v.begin(), v.end(), std::rand);
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, "\t"));
std::cin.get();
return 0;
}
std::generate的第三个参数是个不接受任何参数的函数对象,这里,该函数对象是一个指向std::rand的指针。利用这个函数,为v随机初始化了500个值。
现在,若要统计这500个数里面有多少个可以被5整除和被15整除的,我们可以使用std::count_if:
bool f5(int x)
{
return x % 5 == 0;
}
bool f15(int x)
{
return x % 15 == 0;
}
int count = std::count_if(v.begin(), v.end(), f5);
int count1 = std::count_if(v.begin(), v.end(), f15);
std::cout << count << " " << count1 << std::endl;
f5和f15是通过函数指针的方式传进去的,那么如何通过函数符来完成呢?函数符是一个类对象,通过类方法operator()(),我们可以使用同一个函数符来完成这两项功能。
class fun
{
public:
fun(int x = 1) : mnum(x) {}
bool operator()(int x) { return x % mnum == 0; }
private:
int mnum;
};
通过构造函数,便可以根据传进来的值来决定实际操作。现在,可以这样调用:
int count2 = std::count_if(v.begin(), v.end(), fun(5));
int count3 = std::count_if(v.begin(), v.end(), fun(15));
参数fun(5)创建了一个对象,将5作为了munm的初始值,而std::count_if()则使用该对象来调用operator()()。
还可以使用lambda来完成:
int count4 = std::count_if(v.begin(), v.end(),
[](int x) {
return x % 5 == 0;
});
使用lambda表达式可以替换函数指针或函数符构造函数。
仅当lambda表达式完全由一条返回语句组成时,自动类型推断才有用;否则,则需使用返回类型后置语法:
[](int x) ->int { int y = x; return x - y; }
对于相同的功能,也并非要编写表达式两次,我们可以给lambda指定一个名称:
auto mod5 = [](int x) { return x % 3 == 0; }
count4 = std::count_if(v.begin(), v.end(), mod5);
count5 = std::count_if(v1.begin(), v1.end(), mod5);
亦可像使用平常函数那样使用有名称的lambda:
bool ret = mod5(13);
对于这有一种方式,函数指针方法阻止了内联,因为编译器传统上不会内联其地址被获取的函数,因为函数地址意味着非内联函数。而函数符和lambda通常不会阻止内联。
lambda还可以捕获作用域内的任何动态变量,要捕获的变量可将其放在[]内。使用[=]表示按值传递所有动态的变量,使用[&]可以按引用访问所有的动态变量,也可单独使用[&x],[=x],亦可混合使用[x, &count]。
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 还在手写JSON调教大模型?.NET 9有新玩法
· 复杂业务系统线上问题排查过程
· 通过抓包,深入揭秘MCP协议底层通信
· 记一次.NET MAUI项目中绑定Android库实现硬件控制的开发经历
· 糊涂啊!这个需求居然没想到用时间轮来解决
· Coze Studio:字节跳动 Coze 的开源版本来了!第一时间深度解析
· 复杂业务系统线上问题排查过程
· 在SqlSugar的开发框架的Vue3+ElementPlus前端中增加对报表模块的封装处理,实现常
· 一款超级经典复古的 Windows 9x 主题风格 Avalonia UI 控件库,满满的回忆杀!
· 我给 AI 接上了一个 C# 运行器,结果它学会了自己上网、调试代码