0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++中有函数指针还需要std::function嘛

jf_78858299 来源:码农的荒岛求生 作者:陆小风 2023-02-15 14:13 次阅读

C/C++中可以使用指针指向一段代码,这个指针就叫函数指针,假设有这样一段代码:

#include 

int func(int a) {
  return a + 1;
}

void main() {
   int (*f)(int) = func;
   printf("%p
", f);
}

我们定义了一个函数func,然后使用指针变量f指向该函数,然后打印出变量f指向的地址,代码很简单,然后我们编译一下,看下编译后生成的指令,我们重点关注func函数:

0000000000400526 :
  400526:       55                      push   %rbp
  400527:       48 89 e5                mov    %rsp,%rbp
  40052a:       89 7d fc                mov    %edi,-0x4(%rbp)
  40052d:       8b 45 fc                mov    -0x4(%rbp),%eax
  400530:       83 c0 01                add    $0x1,%eax
  400533:       5d                      pop    %rbp
  400534:       c3                      retq

可以看到,编译好后的函数func位于地址0x400526这个地址,让我们记住这个地址。

然后运行一下编译后生成的程序,想一想这段代码会输出什么呢?

显然应该是func函数的在内存中的地址!

$ ./a.out
0x400526

没有猜错吧,实际上函数指针本质也是一个指针,只不过这个指针指向的不是内存中的一段数据而是内存中的一段代码,就像这样:

图片

看到了吧,我们常说的指针一般都是指向内存中的一段数据,而函数指针指向了内存中的一段代码,在这个示例中指向了内存地址0x400526,在这个地址中保存了函数func的机器指令。

现在你应该明白函数指针了,细心的同学可能会有一个疑问,为什么编译器在生成可执行文件时就知道函数func存放在内存地址0x400526上呢?这不应该是程序被加载到内存后开始运行时才能确定的吗?

这个问题的答案收录在了星球中,星球里的同学查看最新一期的文章即可。

图片

函数指针的作用是可以把一段代码当做一个变量传来传去,主要的用途之一就是回调函数,关于回调函数你可以参考《回调函数的实现原理》这篇文章。

关于回调函数其实是在A模块定义,在B模块被调用,就像这样:

图片

然而有时我们会有这样的场景,我们依然需要在模块A定义函数,同时函数A的运行需要依赖B模块产生的数据,然后将模块A定义的函数和模块B产生的数据一并传递给C模块来调用,就像这样:

图片

此时,单纯的函数指针已经不够用了,因为函数指针只是单纯的指向了内存中的一段代码,我们不但需要将内存中的一段代码同时也需要将内存中的一块数据传递给模块C, 此时你可以定义一个结构体,将代码和数据打包起来 ,就像这样:

typedef void (*func) (int);

struct closure{
  func f;
  int arg;    
};

我们将这个结构体命名为closure,注意看,这个结构中有两部分:

  • 一个指向代码的指针变量
  • 一个保存数据的变量

这样,我们在A模块为指针变量赋值,在B模块为保存数据的变量赋值,然后将此结构体传递给模块C,模块C中可以这样使用:

void run(struct functor func) {
    func->f(func->arg);
}

即,closure既包含了一段代码也包含了这段代码使用的数据,这里的数据也被称为context,即上下文,或者environment,即环境,不管怎么称呼,其实就是函数运行依赖的数据:

图片

而这也正是C++中std::function的目的所在。

单纯的函数指针并没有捕捉上下文的能力 ,这里的上下文就是指代码依赖的数据,你不得不自己动手构造出一个结构体用来存储代码依赖的上下文。

在C++中你没有办法单纯的利用函数指针指向对象的成员函数,就是因为函数指针没有办法捕捉this(指向对象的指针)这个上下文。

std::function的作用本质上和我们刚才定义的结构体区别不大。

利用std::function你不但可以保存一段代码,同时也可以保存必要的上下文,然后在合适的地方基于上下文调用这段代码。

同时std::function也更加通用,你可以用其存储任何可以被调用的对象(callable object),只要有正确的函数签名即可。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C++
    C++
    +关注

    关注

    22

    文章

    2104

    浏览量

    73480
  • 代码
    +关注

    关注

    30

    文章

    4741

    浏览量

    68325
  • 函数指针
    +关注

    关注

    2

    文章

    56

    浏览量

    3775
收藏 人收藏

    评论

    相关推荐

    C/C++回调函数

    列表);最后需要注意的是,指向函数指针变量没有 ++ 和 -- 运算。C++类的静态函数作为回调函数
    发表于 02-11 15:25

    嵌入式-C++函数的重载

    函数名定义,从而形成重载,方便使用,某种层度上函数的重载也是C++三大特性之一的多态的一种形式 三、函数重载的应用场景 #include //利用using指令打开
    发表于 06-28 13:54

    C语言指针函数函数指针详细介绍

    C语言指针函数函数指针详细介绍。。。。。。。
    发表于 03-04 15:27 5次下载

    C++实验--指针

    C++实验--指针
    发表于 12-30 14:50 1次下载

    C++指针”学习建议

    C++指针”学习建议
    发表于 03-31 15:53 3次下载

    c语言函数指针定义,指针函数函数指针的区别

     往往,我们一提到指针函数函数指针的时候,就有很多人弄不懂。下面就由小编详细为大家介绍C语言中函数
    发表于 11-16 15:18 3612次阅读

    C++程序设计教程之函数机制的详细资料说明

    本文档详细介绍的是C++程序设计教程之函数机制的详细资料说明主要内容包括了: 1.函数性质( Function Character ) , 2.指针
    发表于 02-22 11:24 2次下载
    <b class='flag-5'>C++</b>程序设计教程之<b class='flag-5'>函数</b>机制的详细资料说明

    C++封装:this指针

    C++封装:this指针
    的头像 发表于 06-29 14:37 3446次阅读
    <b class='flag-5'>C++</b>封装:this<b class='flag-5'>指针</b>

    讲解C++ function 技术的实现与具体运用

    std::function对象没有初始化任何实际的可调用元素,调用std::function对象将抛出std::bad_
    的头像 发表于 01-19 17:05 4705次阅读

    C++ function技术的实现与具体运用

    std::function对象没有初始化任何实际的可调用元素,调用std::function对象将抛出std::bad_
    的头像 发表于 01-20 09:23 3332次阅读

    std::function简介及模板类声明

    包装下列这几种可调用实体:函数函数指针、成员函数、静态函数、lamda表达式和函数对象。
    的头像 发表于 07-28 15:30 4769次阅读

    C++中如何用虚函数实现多态

    01 — C++函数探索 C++是一门面向对象语言,在C++里运行时多态是由虚函数和纯虚函数
    的头像 发表于 09-29 14:18 1669次阅读

    深度解析C++中的虚函数

    的重要手段。没有虚函数C++C的区别就不大,都需要借助大量的“函数指针”,进行面向对象的程序
    的头像 发表于 02-15 11:14 808次阅读
    深度解析<b class='flag-5'>C++</b>中的虚<b class='flag-5'>函数</b>

    function与invoke的区别

    std::functionstd::invoke是两个不同的东西,功能也不同。std::function 是一个
    的头像 发表于 04-27 15:13 706次阅读

    C++ std::tie函数的作用和用法

    C++std::tie函数的作用就是从元素引用中生成一个tuple元组,其在头文件中定义
    的头像 发表于 07-18 17:28 806次阅读