0x4005b6,在这个地址中保存了函数func的机器指令 。
现在你应该明白函数指针了,细心的同学可能会有一个疑问,为什么编译器在生成可执行文件时就知道函数func存放在内存地址0x4005b6上呢?这不应该是程序被加载到内存后开始运行时才能确定的吗?
函数指针的作用是可以把一段代码当做一个变量传来传去,主要的用途之一就是回调函数 。关于回调函数其实是在A模块定义,在B模块被调用,就像这样:

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

文章插图
此时,单纯的函数指针已经不够用了,因为函数指针只是单纯的指向了内存中的一段代码,我们不但需要将内存中的一段代码同时也需要将内存中的一块数据传递给模块C,此时你可以定义一个结构体,将代码和数据打包起来,就像这样:
typedef void (*func)(int);struct functor {func f;int arg;};我们将这个结构体命名为functor,注意看,这个结构中有两部分:- 一个指向代码的指针变量
- 一个保存数据的变量
void run(struct functor func) {func->f(func->arg);}即,functor既包含了一段代码也包含了这段代码使用的数据,这里的数据也被称为context,即上下文,或者environment,即环境,不管怎么称呼,其实就是函数运行依赖的数据:
文章插图
而这也正是C++中
std::function的目的所在 。单纯的函数指针并没有捕捉上下文的能力,这里的上下文就是指代码依赖的数据,你不得不自己动手构造出一个结构体用来存储代码依赖的上下文 。在C++中你没有办法单纯的利用函数指针指向对象的成员函数,就是因为函数指针没有办法捕捉
this(指向对象的指针)这个上下文 。?注:利用std::function的作用本质上和我们刚才定义的结构体区别不大 。
std::function你不但可以保存一段代码,同时也可以保存必要的上下文,然后在合适的地方基于上下文调用这段代码 。根据上文的介绍,我们也知道
std::function相比函数指针的优势所在,要去理解std::function,只需要理解上面提到的结构体即可 。接下来我们来谈谈std::function的用法以及一步一步实现一个简单的std::function,剖析其原理 。function的基本用法接下来直接展示function的直观用法,我们可以把function想象为一个模板类,调用该模板类的
operator()()小括号运算符重载,执行封装的函数指针,关于std::function具体实现细节,后续再继续说明,函数指针可用于回调功能,函数对象也可用于回调功能,lambda表达式也可用于回调功能,甚至bind绑定适配后的成员函数也可用于回调功能,那么在不确定的情况下,通过function机制这样的泛型机制统一表示,就会很方便 。普通函数:
void hello() {cout << "hello world!" << endl;}void hello_str(string str) {cout << str << endl;}int main() {function<void()> func1 = &hello;// function<void()> func1(&hello); // 两种调用方法均可func1(); //调用func1.operator()() ==> void hello()function<void(string)> func2 = &hello_str;func2("hello world"); //调用func2.operator()(string) ==> void hello_str(string)return 0;}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 路由器每天晚上都关掉好不好路由器每天晚上都关掉会怎么样
- 路由器放在墙边还是角落 路由器放在哪里比较好
- 路由器辐射是手机的多少倍 路由器辐射怎么减少
- 2023年9月22日是安机器的黄道吉日吗 2023年农历八月初八宜安机器吗
- 2023年9月22日适合安装机器吗 2023年9月22日安装机器好吗
- 2023年9月23日是安机器吉日吗 2023年农历八月初九安机器吉日
- 2023年9月23日是安装机器吉日吗 2023年9月23日安装机器行吗
- .net core Blazor+自定义日志提供器实现实时日志查看器
- 干粉灭火器如何使用
- c类火灾用什么灭火器
