本节介绍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中的参数如果是原始函数指针就会报错,需要改成function auto 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中的参数如果是原始函数指针就会报错,需要改成function auto lambda = [=](int value){std::cout << value << a << std::endl;}; ForEach(values, lambda); }