当前位置:首页 > 科技  > 软件

让人压抑的 C++:记一个函数指针的问题

来源: 责编: 时间:2023-11-28 17:12:00 160观看
导读最近因为项目要求用c++,之前一直很讨厌c++,没办法只能短时间弥补c++的知识,项目中需要定义一个函数指针类型的vector,本以为很简单的问题,结果调试了一天,才发现错在哪里。多余的std::function先上代码吧,这里有一个测试代码

最近因为项目要求用c++,之前一直很讨厌c++,没办法只能短时间弥补c++的知识,项目中需要定义一个函数指针类型的vector,本以为很简单的问题,结果调试了一天,才发现错在哪里。tJV28资讯网——每日最新资讯28at.com

tJV28资讯网——每日最新资讯28at.com

多余的std::function

先上代码吧,这里有一个测试代码,为什么要有测试代码?是因为下面的方式我在最开始验证该种实现时打印的地址是对的,但是之后一段时间就不对了,所以摘出来写了一个测试代码。tJV28资讯网——每日最新资讯28at.com

代码非常简单:使用using std::function的方式定义一个函数指针类型func_t,然后实现三个print函数,在main函数中定义一个vector存放三个函数的地址,打印三个函数的实际地址,之后遍历vector打印存放的元素值。tJV28资讯网——每日最新资讯28at.com

#include <iostream>#include <vector>#include <functional>// 定义 std::function 类型的函数指针别名using func_t = std::function<void(int, void*, size_t, size_t, void*)>;// 示例函数void print(int x, void* y, size_t a, size_t b, void* c) {    std::cout << "print hello/n";}void print1(int x, void* y, size_t a, size_t b, void* c) {    std::cout << "print1 hello/n";}void print2(int x, void* y, size_t a, size_t b, void* c) {    std::cout << "print2 hello/n";}int main() {    // 创建一个存储 std::function 类型的函数指针对象的 std::vector    std::vector<func_t> vec;    // 使用 push_back 将函数指针对象添加到 std::vector 中    vec.push_back(print);    vec.push_back(print1);    vec.push_back(print2);    printf("%x, %x, %x/n", print, print1, print2);    // 遍历 std::vector 并依次调用存储的函数指针对象    for (const auto& func : vec) {        // 调用函数指针对象        //func(0, nullptr, 0, 0, nullptr);        printf("%x./n", func);    }    return 0;}

执行后的结果:tJV28资讯网——每日最新资讯28at.com

tJV28资讯网——每日最新资讯28at.com

我最开始的理解是vector内部存放的地址就是三个函数的地址。结果打印的结果意料之外啊,居然一样,我尝试在for循环遍历时执行该地址函数,结果还能正常运行。最开始以为是vector遍历取值的问题,后来经过一番验证没问题,最后锁定要函数指针定义上。tJV28资讯网——每日最新资讯28at.com

我尝试切换一种函数指针定义,使用我最原始的方式:tJV28资讯网——每日最新资讯28at.com

// 定义 std::function 类型的函数指针别名//using func_t = std::function<void(int, void*, size_t, size_t, void*)>;using func_t = void (*)(int, void*, size_t, size_t, void*);

tJV28资讯网——每日最新资讯28at.com

运行后发现这次是对的了:tJV28资讯网——每日最新资讯28at.com

tJV28资讯网——每日最新资讯28at.com

tJV28资讯网——每日最新资讯28at.com

最后经过一番查找,得出结论如下:tJV28资讯网——每日最新资讯28at.com

实际上,std::function 存储函数指针时,不直接存储函数指针本身的地址,而是存储了函数指针对象的一些信息,因此直接使用 %x 来打印 std::function 存储的函数指针可能无法获得正确的地址。tJV28资讯网——每日最新资讯28at.com

在标准库 中,std::function 是一个函数包装器,它可以包含各种可调用对象(函数指针、函数对象、成员函数指针、Lambda 表达式等)。因此,std::function 内部存储了被包装对象的地址以及其他信息,而不是直接将被包装对象的地址暴露给用户。tJV28资讯网——每日最新资讯28at.com

由于 std::function 对象的内部结构不同于原始函数指针, std::function 对象存储了更多的信息,所以直接打印 std::function 对象的地址并不会得到和原始函数指针相同的值,打印它的地址并不等同于打印函数指针的地址。tJV28资讯网——每日最新资讯28at.com

所以,如果需要存储函数指针并在之后通过 std::function 来调用它们,可以直接通过 std::function 来调用并且可以得到预期的结果,但是打印地址是不保证能够得到和原始函数指针相同的地址(这也是我遇到了几次和原始函数指针一致的时候,这也是造成我更迷茫的原因)。tJV28资讯网——每日最新资讯28at.com

tJV28资讯网——每日最新资讯28at.com

那为什么打印的值一样呢?tJV28资讯网——每日最新资讯28at.com

因为在遍历 std::vector<std::function> 时,即使它们指向不同的函数,它们的内部指针值可能是相同的,这是因为 std::function 可以包装不同的可调用对象,但它们内部可能使用相同的机制来存储函数指针或者函数对象的地址。因此,打印 std::function 内部存储的函数指针值可能会得到相同的结果。但这不应该影响 std::function 执行其持有的不同函数的能力。tJV28资讯网——每日最新资讯28at.com

总结

tJV28资讯网——每日最新资讯28at.com

如果你也需要直接获取存储的函数指针的地址(C语言的习惯),最好还是直接使用原始的函数指针,而不是通过 std::function 来存储和获取函数指针的地址。tJV28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-34923-0.html让人压抑的 C++:记一个函数指针的问题

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 大型直播活动保障S13的实践和思考

下一篇: Istio新架构揭秘:环境化Mesh

标签:
  • 热门焦点
  • 一加Ace2 Pro官宣:普及16G内存 引领24G

    一加Ace2 Pro官宣:普及16G内存 引领24G

    一加官方今天继续为本月发布的新机一加Ace2 Pro带来预热,公布了内存方面的信息。“淘汰 8GB ,12GB 起步,16GB 普及,24GB 引领,还有呢?#一加Ace2Pro#,2023 年 8 月,敬请期待。”同时
  • MIX Fold3包装盒泄露 新机本月登场

    MIX Fold3包装盒泄露 新机本月登场

    小米的全新折叠屏旗舰MIX Fold3将于本月发布,近日该机的真机包装盒在网上泄露。从图上来看,新的MIX Fold3包装盒在外观设计方面延续了之前的方案,变化不大,这也是目前小米旗舰
  • 卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    卢伟冰长文解析K60至尊版 对Redmi有着里程碑式的意义

    在今天的Redmi后性能时代战略发布会结束之后,Redmi总经理卢伟冰又带来了一篇长文,详解了为什么 Redmi 要开启后性能时代?为什么选择和 MediaTek、Pixelworks 深度合作?以及后性
  • 把LangChain跑起来的三个方法

    把LangChain跑起来的三个方法

    使用LangChain开发LLM应用时,需要机器进行GLM部署,好多同学第一步就被劝退了,那么如何绕过这个步骤先学习LLM模型的应用,对Langchain进行快速上手?本片讲解3个把LangChain跑起来
  • 如何通过Python线程池实现异步编程?

    如何通过Python线程池实现异步编程?

    线程池的概念和基本原理线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任
  • 共享单车的故事讲到哪了?

    共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • “又被陈思诚骗了”

    “又被陈思诚骗了”

    作者|张思齐 出品|众面(ID:ZhongMian_ZM)如今的国产悬疑电影,成了陈思诚的天下。最近大爆电影《消失的她》票房突破30亿断层夺魁暑期档,陈思诚再度风头无两。你可以说陈思诚的
  • ESG的面子与里子

    ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大&ldquo;烤&rdquo;之下的除了众生,还有各大企业发布的ESG报告。ESG是&ldquo;环境保
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top