本节介绍c++函数指针。在一些源码中经常能看到c++函数指针,但之前一直觉着这一块比较复杂,就一直没去仔细研究,终于有时间去仔细研究这一块内容了。
-
c风格的函数指针
- 函数指针是指将一个函数赋值给一个变量的方法,可以将函数作为一个参数传递给另一个函数,简单的使用示例如下
-
#include <iostream>void PrintMessage() {std::cout << "Hello World!" << std::endl; }int main() {//一般情况下调用函数的方式//PrintMessage();//函数指针//取一个函数的地址赋值给一个变量auto function = PrintMessage; //不加()//函数就是cpu指令,当编译完成代码后,函数处在二进制文件的某个地方//赋值给一个变量后可以向之前调用函数一样调用function();function(); //打印 "Hello World!"std::cin.get(); }
- 上述示例中是通过auto来接收,接下来看一下PrintMessage具体的返回值类型。
-
#include <iostream>void PrintMessage() {std::cout << "Hello World!" << std::endl; }int main() {//一般情况下调用函数的方式//PrintMessage();//函数指针//取一个函数的地址赋值给一个变量auto function = PrintMessage; //不加()//函数就是cpu指令,当编译完成代码后,函数处在二进制文件的某个地方//赋值给一个变量后可以向之前调用函数一样调用function();function(); //打印 "Hello World!"//实际PrintMessage返回的类型是void(*function)()//实际的类型是void(*)(),最后一个括号里面的放的是函数的参数类型,function是我们给这个返回类型起的名字void(*pcop)();pcop = PrintMessage;pcop();//打印 "Hello World!"//上述的void(*pcop)()可以使用typedef,将别名写在如下位置,看起来可能有点奇怪,但确实是这样的typedef void(*testFunctionPoint)();testFunctionPoint heiheihei = PrintMessage;heiheihei();//打印 "Hello World!"std::cin.get(); }
- 接下来展示函数指针的函数包含参数的示例
-
#include <iostream>void PrintMessage(int a) {std::cout << "Hello World! " << a <<std::endl; }int main() {//一般情况下调用函数的方式//PrintMessage();//函数指针//取一个函数的地址赋值给一个变量auto function = PrintMessage; //不加()//函数就是cpu指令,当编译完成代码后,函数处在二进制文件的某个地方//赋值给一个变量后可以向之前调用函数一样调用function(1);function(2); //打印 "Hello World!"//实际PrintMessage返回的类型是void(*function)()//实际的类型是void(*)(),最后一个括号里面的放的是函数的参数类型,function是我们给这个返回类型起的名字void(*pcop)(int);pcop = PrintMessage;pcop(5);//打印 "Hello World!"//上述的void(*pcop)()可以使用typedef,将别名写在如下位置,看起来可能有点奇怪,但确实是这样的typedef void(*testFunctionPoint)(int);testFunctionPoint heiheihei = PrintMessage;heiheihei(6);//打印 "Hello World!"std::cin.get(); }
- 上述描述的都是函数指针的原理,接下来大概展示函数指针的使用场景。
-
#include <iostream> #include <vector> void PrintValue(int value) {std::cout << value << std::endl; }void ForEach(const std::vector<int>& values, void(*func)(int)) {for (int value:values){func(value);} }int main() {std::vector<int> values = {1,4,6,7,9};//创建一个函数,迭代遍历values中的所有元素,并将值进行打印ForEach(values, PrintValue);std::cin.get(); }
-
c++lambda表达式
- lambda表达式是指用一种匿名函数的创建函数,用这种方式创建函数不需要实际创建一个函数。只要有一个函数指针,都可以使用lambda。接下来通过代码展示lambda。
- 上述的代码展示的是用lambda替换上节所讲述的PrintValue函数指针。()中传入的是lambda的{}中所需的参数,上述的func(value)实际上调用就是[](int value){std::cout << value << std::endl;}。
- 接下来事例展示将一个函数传递给一个API,以便在未来的某个时间,可以为我们调用这个函数,现在不能掉用该函数,因为函数所需要的数据还为准备好,所以需要延迟调用。lambda可以很好的实现上述需求,代码实现如下:
- []里面放的是lambda的捕获,当需要将外部的变量传入lambda{}中时用到。
-
#include <iostream> #include <vector> #include <functional>void ForEach(std::vector<int> vlaues ,const std::function<void(int)>& func) {for(int value:vlaues)func(value); }int main() {std::vector<int> values = {2,5,7,9,4};int a = 10;//想要在lambda中调用main函数的a变量,直接调用会报错//可以通过[=]值传递进行调用,也可以通过[&]传递进行调用//此时ForEach中的参数如果是原始函数指针就会报错,需要改成functionauto lambda = [=](int value){std::cout << value << a << std::endl;};ForEach(values, lambda);}
- std::find_if,迭代器查找值
-
#include <iostream> #include <vector> #include <functional> #include <algorithm>void ForEach(std::vector<int> vlaues ,const std::function<void(int)>& func) {for(int value:vlaues)func(value); }int main() {std::vector<int> values = {2,5,7,9,4};//用find_if查找vector中第一个比3大的元素auto it = std::find_if(values.begin(),values.end(),[](int value){return value>3;} );std::cout << *it << std::endl;int a = 10;//想要在lambda中调用main函数的a变量,直接调用会报错//可以通过[=]值传递进行调用,也可以通过[&]传递进行调用//此时ForEach中的参数如果是原始函数指针就会报错,需要改成functionauto lambda = [=](int value){std::cout << value << a << std::endl;};ForEach(values, lambda);}