• 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表达式)。

  • 相关阅读:
    广和通正式发布工业级低功耗单频双模GNSS模组G030&G031
    Nginx的mirror指令能干啥?
    PyCharm新手入门
    Oracle导出sequence
    Vue中的$nextTick
    【JavaScript复习十五】数组小练习
    OpenP2P实现内网穿透远程办公
    超硬核的Move Dev Meetup上海线下交流会圆满结束
    【笑小枫的SpringBoot系列】【十七】SpringBoot文件上传下载
    家政预约上门app开发小程序同城服务
  • 原文地址:https://blog.csdn.net/a2998658795/article/details/126068605