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

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

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

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

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

多余的std::function

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

代码非常简单:使用using std::function的方式定义一个函数指针类型func_t,然后实现三个print函数,在main函数中定义一个vector存放三个函数的地址,打印三个函数的实际地址,之后遍历vector打印存放的元素值。ca328资讯网——每日最新资讯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;}

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

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

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

我尝试切换一种函数指针定义,使用我最原始的方式:ca328资讯网——每日最新资讯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*);

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

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

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

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

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

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

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

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

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

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

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

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

总结

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

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

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

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

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

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

标签:
  • 热门焦点
  • 7月安卓手机性能榜:红魔8S Pro再夺榜首

    7月份的手机市场风平浪静,除了红魔和努比亚带来了两款搭载骁龙8Gen2领先版处理器的新机之外,别的也想不到有什么新品了,这也正常,通常6月7月都是手机厂商修整的时间,进入8月份之
  • 十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • 在线图片编辑器,支持PSD解析、AI抠图等

    自从我上次分享一个人开发仿造稿定设计的图片编辑器到现在,不知不觉已过去一年时间了,期间我经历了裁员失业、面试找工作碰壁,寒冬下一直没有很好地履行计划.....这些就放在日
  • 本地生活这块肥肉,拼多多也想吃一口

    出品/壹览商业 作者/李彦编辑/木鱼拼多多也看上本地生活这块蛋糕了。近期,拼多多在App首页&ldquo;充值中心&rdquo;入口上线了本机生活界面。壹览商业发现,该界面目前主要
  • 华为HarmonyOS 4.0将于8月4日发布 或搭载AI大模型技术

    华为宣布HarmonyOS4.0将于8月4日正式发布。此前,华为已经针对开发者公布了HarmonyOS4.0,以便于开发者提前进行适配,也因此被曝光出了一些新系统的特性
  • iQOO Neo8系列新品发布会

    旗舰双芯 更强更Pro
  • OPPO K11样张首曝:千元机影像“卷”得真不错!

    一直以来,OPPO K系列机型都保持着较为均衡的产品体验,历来都是2K价位的明星机型,去年推出的OPPO K10和OPPO K10 Pro两款机型凭借各自的出色配置,堪称有
  • 朋友圈可以修改可见范围了 苹果用户可率先体验

    近日,iOS用户迎来微信8.0.27正式版更新,除了可更换二维码背景外,还新增了多项实用功能。在新版微信中,朋友圈终于可以修改可见范围,简单来说就是已发布的朋友圈
Top