C++回调函数以及epoll中回调函数的使用
回调函数是一种常用的编程技术,它允许程序在运行时将一个函数作为参数传递给另一个函数,以实现更加灵活和可扩展的功能。在C++中,回调函数通常被实现为函数指针或者函数对象。
函数指针是指向函数的指针变量,可以通过它来调用函数。函数对象是一种可调用对象,它是一个类的对象,其中定义了一个operator()函数,可以像普通函数一样进行调用。下面是一个简单的回调函数示例,使用函数指针作为回调函数:
#include <iostream>// 定义回调函数类型
typedef void (*Callback)(int);// 回调函数
void my_callback(int x) {std::cout << "Callback function called with argument " << x << std::endl;
}// 接受回调函数作为参数的函数
void do_something(Callback callback) {// 执行某些操作int result = 42;// 调用回调函数callback(result);
}int main() {// 调用do_something函数,并传递回调函数my_callback作为参数do_something(my_callback);return 0;
}
在上面的示例中,我们定义了一个回调函数类型Callback,该类型是一个函数指针,接受一个int类型的参数并返回void。然后我们定义了一个my_callback函数,它接受一个int类型的参数,并打印出该参数的值。接着我们定义了一个do_something函数,它接受一个Callback类型的参数,并执行一些操作后调用该回调函数。
在主函数中,我们调用do_something函数,并传递my_callback函数作为参数。当do_something函数执行完成后,它会调用传递进来的回调函数my_callback,并将一个int类型的参数传递给它。
除了函数指针外,C++中还可以使用函数对象实现回调函数。下面是一个使用函数对象的回调函数示例:
#include <iostream>// 回调函数对象
class MyCallback {
public:void operator()(int x) const {std::cout << "Callback function called with argument " << x << std::endl;}
};// 接受回调函数对象作为参数的函数
void do_something(const MyCallback& callback) {// 执行某些操作int result = 42;// 调用回调函数对象callback(result);
}int main() {// 调用do_something函数,并传递回调函数对象MyCallback作为参数do_something(MyCallback());return 0;
}
在这个示例中,我们定义了一个回调函数对象MyCallback,它是一个类,其中定义了一个operator()函数,接受一个int类型的参数并返回void。我们还定义了一个do_something函数,它接受一个MyCallback类型的参数,并执行一些操作后调用该回调函数对象。
在主函数中,我们调用do_something函数,并传递MyCallback对象作为参数。当do_something函数执行完成后,它会调用传递进来的回调函数对象MyCallback,并将一个int类型的参数传递给它。
总的来说,回调函数是一种非常有用的编程技术,它可以使程序更加灵活和可扩展。通过将一个函数作为参数传递给另一个函数,我们可以在运行时动态地改变程序的行为。无论是使用函数指针还是函数对象,回调函数都是实现回调机制的常用方式。
epoll中回调函数的使用
epoll_wait函数会阻塞进程,直到有一个或多个文件描述符准备好进行读或写或者出现错误或超时。当epoll_wait返回时,程序需要通过遍历epoll_event数组来确定哪些文件描述符准备好进行读或写或者出现错误或超时,从而进行相应的处理。
在epoll_event结构体中,有一个data成员,它可以存储任意的用户数据。在epoll_wait函数中,我们可以将某个文件描述符关联的回调函数指针保存在data成员中。当epoll_wait函数返回并确定该文件描述符已准备好读或写时,程序会调用该回调函数来进行相应的处理。
以下是一个使用回调函数的epoll示例:
#include <sys/epoll.h>
#include <unistd.h>
#include <iostream>// 定义回调函数类型
typedef void (*Callback)(int);// 回调函数
void read_callback(int fd) {char buf[1024] = {0};int ret = read(fd, buf, sizeof(buf));if (ret > 0) {std::cout << "Read data from file descriptor " << fd << ": " << buf << std::endl;} else {std::cout << "Error reading data from file descriptor " << fd << std::endl;}
}// 添加文件描述符到epoll实例
void add_epoll(int epoll_fd, int fd, Callback callback) {epoll_event event;event.events = EPOLLIN;event.data.ptr = (void*)callback; // 保存回调函数指针到data成员epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &event);
}int main() {int epoll_fd = epoll_create(10);int fd1 = STDIN_FILENO;int fd2 = STDOUT_FILENO;// 添加文件描述符到epoll实例add_epoll(epoll_fd, fd1, read_callback);add_epoll(epoll_fd, fd2, read_callback);// 监听文件描述符事件epoll_event events[10];while (true) {int n = epoll_wait(epoll_fd, events, sizeof(events)/sizeof(epoll_event), -1);for (int i = 0; i < n; i++) {Callback callback = (Callback)events[i].data.ptr; // 获取回调函数指针int fd = events[i].data.fd;callback(fd); // 调用回调函数进行处理}}return 0;
}
在这个示例中,我们定义了一个read_callback函数作为回调函数,用于读取文件描述符中的数据。我们还定义了一个add_epoll函数,它将一个文件描述符及其对应的回调函数添加到epoll实例中。在add_epoll函数中,我们将回调函数指针保存在epoll_event结构体的data.ptr成员中。在主函数中,我们使用epoll_wait函数监听文件描述符事件,并在事件触发时通过回调函数处理文件描述符中的数据。
需要注意的是,在使用回调函数时,必须保证回调函数的生命周期长于epoll_wait函数的调用。否则,在回调函数执行期间,可能会出现回调函数所引用的数据已经被销毁的情况,导致程序崩溃或产生其他不可预料的错误。
相关文章:
C++回调函数以及epoll中回调函数的使用
回调函数是一种常用的编程技术,它允许程序在运行时将一个函数作为参数传递给另一个函数,以实现更加灵活和可扩展的功能。在C中,回调函数通常被实现为函数指针或者函数对象。 函数指针是指向函数的指针变量,可以通过它来调用函数。…...

0基础学习软件测试有哪些建议
其实现在基础的资料和视频到处都是,就是看你有没有认真的去找学习资源了,去哪里学习都是要看你个人靠谱不靠谱,再好的教程和老师,你自己学习不进去也是白搭在正式选择之前,大可以在各种学习网站里面找找学习资源先自己…...

MySQL数据类型
文章目录一、数据类型分类二、数值类型1. tinyint 类型2. bit 类型3. int 类型4. float 类型5. decimal 类型三、字符串类型1. char 类型2. varchar 类型3. char 和 varchar 比较4.日期和时间类型5. enum 和 set一、数据类型分类 数据类型本质也是一种约束! 如果插入…...

【设计模式】从Mybatis源码中学习到的10种设计模式
文章目录 一、前言二、源码:学设计模式三、类型:创建型模式1. 工厂模式2. 单例模式3. 建造者模式 四、类型:结构型模式1. 适配器模式2. 代理模式3. 组合模式4. 装饰器模式 五、类型:行为型模式1. 模板模式2. 策略模式3. 迭代器模式…...

爬虫攻守道 - 猿人学第20题 - 殊途同归
写在开头 这题也是,自己搞顶多追踪到wasm代码,然后就走不下去了。找了2个参考方案,自己做的过程中还又遇到些新的问题,下面做个记录。解法1参考文章解法2参考文章 解法1:追根溯源 在 JS 代码中追踪到 Payload 赋值位…...
4.11日报
synchronized 和 ReentrantLock 区别是什么? synchronized 早期的实现比较低效,对比 ReentrantLock,大多数场景性能都相差较大,但是在 Java 6 中对 synchronized 进行了非常多的改进。 主要区别如下: ReentrantLock …...

【LeetCode每日一题: 1039. 多边形三角剖分的最低得分 | 暴力递归=>记忆化搜索=>动态规划 | 区间dp 】
🍎作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎 🍎座右…...

Okio 网络提速
文章目录网络数据处理流程Page Cache传统 I/O 拷贝的性能问题零拷贝技术DMA 技术零拷贝技术分类mmapsendfilespliceDirect I/O零拷贝技术性能分析小结OkioOkio 的使用Okio 网络提速的原理Okio 总结总结网络数据处理流程 在讲 Okio 之前,为了能更好的了解 Okio 的优…...

自动驾驶企业面临哪些数据安全挑战?
近期,“特斯拉员工被曝私下分享用户隐私”不可避免地成了新闻热点,据说连马斯克也不能幸免。 据相关媒体报道,9名前特斯拉员工爆料在2019年至2022年期间,特斯拉员工通过内部消息系统私下分享了一些车主车载摄像头记录的隐私视频和…...

Doris(2):Doris编译部署
1 Doris编译 Apache Doris提供直接可以部署的版本压缩包:https://cloud.baidu.com/doc/PALO/s/Ikivhcwb5 也可以自行编译压缩包后使用(推荐) 1.1 使用 Docker 开发镜像编译(推荐) 这个是官方文档推荐的,…...

使用MyBatis实现简单查询
文章目录一,创建数据库与表(一)在Navicat里创建MySQL数据库testdb(二)创建用户表 - t_user(三)在用户表里插入3条记录二,案例演示MyBatis基本使用(一)创建Mav…...
C指针(*point)[4]和char *point[4]
char (*point)[4] // 数组指针。 a[3][4] // 先申明二维数组,用它来指向这个二维数组. char *point[4] // 指针数组。 a[4][5] // 一连串的指针. char (*point)[4] // 一个指针,指向有4个元素的数组;占内存大小为 4 个字节 ch…...

【Bard】谷歌的人工智能工具—Bard初体验
文章目录一、Bard介绍二、Bard体验1、加入Bard的候补名单2、登入Bard篇3、使用Bard篇(1)提供三种预选方式✨(2)创作生成各类文案(3)无生成图画能力(4)支持语音转文本输入✨ÿ…...

2022国赛30:windows脚本题解析
大赛试题内容: ( 九) ) 脚本 【任务描述】 为了减少重复性任务的工作量,节省人力和时间,请采用脚本,实现快速批量的操作。 1.在 windows4 上编写 C:\CreateFile.ps1 的 powershell 脚本,创建20 个文件 C:\test\File00.txt 至 C:\test\File19.txt,如果文件存在,则首先删除…...

Excel常用函数公式20例
目录 一、【IF函数条件判断】 二、【多条件判断】 三、【条件求和】 四、【多条件求和】 五、【条件计数】 六、【多条件计数】 七、【条件查找】 八、【多条件查找】 九、【计算文本算式】 十、【合并多个单元格内容】 十一、【合并带格式的单元格内容】 十二、…...

233:vue+openlayers绘制渐变填充色的圆形、多边形
第233个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayer中绘制带有渐变填充色的圆形、多边形。这里用canvas的方式去渲染,用到了DEVICE_PIXEL_RATIO,设备上的物理像素与设备无关像素 (dips) 之间的比率 (window.devicePixelRatio)。 直接复制下面的 vue+openlayer…...

Flink的窗口机制
窗口机制 tumble(滚动窗口) hop(滑动窗口) session(会话窗口) cumulate(渐进式窗口) Over(聚合窗口) 滚动窗口(tumble) 概念 滚…...

了解分布式Session
大家好,我这名CRUD工程师又来了,最近我的一个同事突然在看分布式Seesion的问题,然后我们两个也是互相讨论了一下,今天我就想着把分布式Session的知识点好好的梳理一下。 在很多系统中,用户的登录功能都是用Session去实…...

仿真创新大赛—国三省一 智能鱼缸(proteus)(stm32)
⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩去年下半年参加了全国仿真创新大赛,也是取得了国赛三等奖,省赛一等奖的好成绩。 ⏩本篇文章对我们的参赛作品《智能鱼缸》做一个简介。 ⏩感…...

【ARMv8 编程】A64 数据处理指令——位域字节操作指令
有些指令将字节、半字或字扩展到寄存器大小,可以是 X 或 W。这些指令存在于有符号(SXTB、SXTH、SXTW)和无符号(UXTB、UXTH)变体中,并且是适当的位域操作指令。 这些指令的有符号和无符号变体都将字节、半字…...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...

MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...