• C++:函数对象Functor(仿函数)与匿名函数对象(Lambda表达式)详细介绍以及底层实现。


    1函数对象Functor(仿函数)

    1.1概念:

    函数对象就是类对象,生成这个类对象的类中,拥有一个小括号运算符重载函数。

    重载了小括号运算符的类的类对象,就叫函数对象。

    1.2代码实例:

    1. #include
    2. using namespace std;
    3. template <class T1>
    4. class A
    5. {
    6. T1 name;
    7. public:
    8. A(T1 name)
    9. {
    10. this->name=name;
    11. }
    12. void operator()()
    13. {
    14. cout<<this->name<
    15. }
    16. };
    17. int main()
    18. {
    19. A a("da jia hao");
    20. a();
    21. return 0;
    22. }

    1.3函数对象相较于普通函数与函数指针的调用效率要高很多(

    1.3.1当我们用普通函数的时候:像下面这种情况,每次都需要回调,特别的繁琐。

    注意:在这个代码里面,即使我们在函数前面都加上inline变成内联函数,也是不行的,因为我们使用的是函数指针,即使变成了内联函数,我们还是需要回调。

    1. #include
    2. using namespace std;
    3. template <class T>
    4. T my_bigger(T a,T b)
    5. {
    6. return a>b?a:b;
    7. }
    8. template <class T>
    9. T my_less(T a,T b)
    10. {
    11. return a>b?b:a;
    12. }
    13. template <class T,class Compare>
    14. T my_compare(T a, T b,Compare f)
    15. {
    16. return f(a,b);
    17. }
    18. int main()
    19. {
    20. cout<< my_compare<int>(10,20,my_less<int>)<
    21. cout<<my_compare<int>(10,20,my_bigger<int>)<
    22. return 0;
    23. }

    1.3.2使用函数对象就可以解决这个问题,因为使用函数对象就相当于在函数面前加上一个inline,效率会提升,代码如下:

    1. #include
    2. using namespace std;
    3. template <class T,class Compare>
    4. T my_compare(T a, T b,Compare f)
    5. {
    6. return f(a,b);
    7. }
    8. template <class T>
    9. class A
    10. {
    11. public:
    12. T operator()(T a,T b)
    13. {
    14. return a>b?a:b;
    15. }
    16. };
    17. template <class T>
    18. class B
    19. {
    20. public:
    21. T operator()(T a,T b)
    22. {
    23. return a>b?b:a;
    24. }
    25. };
    26. int main()
    27. {
    28. cout<<my_compare(10,20,A<int>())<
    29. cout<<my_compare(10,20,B<int>())<
    30. return 0;
    31. }

    2.匿名函数对象Lambda表达式:

    2.1使用形式:

    auto + 名字 =[]()->返回值{};

    具体介绍:
    1.[] 中括号表示函数对象的构造函数中是否接收外部变量。 [&] ,表示使用引用的方式获取外部变量 [=],表示使用值的拷贝的方式获取外部变量。

    2.() 这个小括号是就函数对象中的小括号符后面的参数列表。

    3.->返回值,需要就放,不需要就不放。根据自己需要,任君选择。

    4.{...} 就是函数对象的小括号运算符的函数体。

    2.2代码实例:

    2.2.1第一个当[]里面没用东西时:

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. public:
    6. A()
    7. {
    8. }
    9. void operator()()
    10. {
    11. }
    12. };
    13. int main()
    14. {
    15. auto f=[]()->void{cout<<"我是大哥"<
    16. f();
    17. return 0;
    18. }

    2.2.2第二个当[]里面有东西时:(实现交换)

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. int a;
    6. public:
    7. A(int &a)
    8. {
    9. this->a=a;
    10. }
    11. void operator()()
    12. {
    13. }
    14. };
    15. int main()
    16. {
    17. int a=10;
    18. int b=20;
    19. auto f=[&]()->void
    20. {
    21. int temp=a;
    22. a=b;
    23. b=temp;
    24. };
    25. f();
    26. cout<
    27. cout<
    28. return 0;
    29. }

    2.2.3注意点:

    当时候=号的时候,底层实现用的是const,这样就不能进行赋值等一系列操作,如下代码,我们可以加上一个mutable,C++11所提供的新的关键字mutale,是一种易变是的修饰符。当然下面这个代码肯定不能实现交换,我只是用来做一个说明。

    1. #include
    2. using namespace std;
    3. class A
    4. {
    5. int a;
    6. public:
    7. A(int &a)
    8. {
    9. this->a=a;
    10. }
    11. void operator()()
    12. {
    13. }
    14. };
    15. int main()
    16. {
    17. int a=10;
    18. int b=20;
    19. auto f=[=]()mutable
    20. {
    21. int temp=a;
    22. a=b;
    23. b=temp;
    24. };
    25. f();
    26. return 0;
    27. }

    3总结:

    在C++中Funtor也被称为函数符:

    函数符就有四种表现形式:

    1.全局函数指针,2.成员函数指针,3.函数对象,4.Lambda匿名函数对象(Lambda表达式)。

  • 相关阅读:
    基于springboot实现数码论坛系统设计与实现系统【项目源码+论文说明】计算机毕业设计
    垃圾收集算法
    前端技能树,面试复习第 51 天—— Vue 项目性能优化方案
    什么是重绘和回流(重排)?什么情况下会用到?如何减少
    分布式数据库难题(一):数据分区
    大学计算机毕业设计真的很难完成吗?(资源持续更新~~)
    【毕业设计】56-辅助驾驶系统的视觉检测\超声波\图像识别\装置研究与设计(原理图工程、仿真工程、低重复率设计文档、答辩PPT、开题报告)
    ssm基于java的儿童成长记录系统
    基于Java+SpringBoot+Vue前后端分离秒杀系统设计和实现
    汉堡炸鸡快餐店商城小程序的作用是什么
  • 原文地址:https://blog.csdn.net/a2998658795/article/details/126068605