C++之STL(九)

1、函数对象

什么适合推荐使用函数对象?

需要状态的函数调用:

  • 需要状态的函数调用:
    • 函数对象可以包含成员变量,可以在多次调用中保持状态。这在某些算法中非常有用。
  • 提高性能:

    • 编译器可以更好地优化函数对象,因为它们是具体的类型,而不是函数指针或 std::function,这减少了间接调用的开销。
    • 内联(inline)函数对象的调用可以减少函数调用的开销。
  • 灵活的接口:
    • 函数对象可以有多个重载或模板版本,以适应不同的调用场景。
    • 可以使用模板参数来创建更通用和高效的代码。
  • 用于标准库算法:

    • 标准模板库(STL)的算法,如 std::sort, std::find_if, std::for_each 等,通常需要一个可调用对象作为参数。使用函数对象可以方便地传递复杂的行为。

2、自定义函数对象

第二个()为参数

#include <iostream>
using namespace std;

class FunObj
{
public:
    void operator()()
    {
        std::cout << "Hello, World!" << std::endl;
    }

    void operator()(int n)
    {
        std::cout << n << std::endl;
    }
};

int main() {
    FunObj fo;
    fo();
    fo(1);

    // 也可以构造匿名对象FunObj()
    FunObj()();
    return 0;
}

// 输出
Hello, World!
1
Hello, World!

3、函数对象与容器

#include <iostream>
using namespace std;

#include <map>

int main() {
    map<int, string> mapTest;
    mapTest.insert(map<int, string>::value_type(1, "aaaa"));
    mapTest.insert(map<int, string>::value_type(3, "cccc"));
    mapTest.insert(map<int, string>::value_type(2, "bbbb"));

    for(map<int, string>::const_iterator it = mapTest.begin(); it != mapTest.end(); ++it)
    {
        cout << it->first << "  " << it->second << endl;
    }
    return 0;
}

// 输出
1  aaaa
2  bbbb
3  cccc

从代码中可以看到,是即使我们先插入3,然后再插入2,打印出来却是按照顺序,这是因为map是一个类模板,模板中的第三个参数less是一个结构体,也就是类,里面是一个函数对象,也就是调用这个函数对象来进行比较大小。

  template <typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
	    typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
    class map
    { ...}

// less定义
  template<typename _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
      _GLIBCXX14_CONSTEXPR
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };

当然我们也可以用本生提供的greater<>来进行从大到小排序

#include <iostream>
using namespace std;

#include <map>

int main() {
    map<int, string, greater<int>> mapTest;
    mapTest.insert(map<int, string>::value_type(1, "aaaa"));
    mapTest.insert(map<int, string>::value_type(3, "cccc"));
    mapTest.insert(map<int, string>::value_type(2, "bbbb"));

    for(map<int, string, greater<int>>::const_iterator it = mapTest.begin(); it != mapTest.end(); ++it)
    {
        cout << it->first << "  " << it->second << endl;
    }
    return 0;
}

// 输出
3  cccc
2  bbbb
1  aaaa

当然我们也可以自己提供函数对象

#include <iostream>
using namespace std;

#include <map>

struct MyGreater
{
    bool operator()(int left, int right) const
    {
        return left > right;
    }
};
int main() {
    map<int, string, MyGreater> mapTest;
    mapTest.insert(map<int, string>::value_type(1, "aaaa"));
    mapTest.insert(map<int, string>::value_type(3, "cccc"));
    mapTest.insert(map<int, string>::value_type(2, "bbbb"));

    for(map<int, string, MyGreater>::const_iterator it = mapTest.begin(); it != mapTest.end(); ++it)
    {
        cout << it->first << "  " << it->second << endl;
    }
    return 0;
}

// 输出
3  cccc
2  bbbb
1  aaaa

4、函数对象与算法

#include <iostream>
using namespace std;

#include <map>
#include <vector>
#include <algorithm>

void PrintFun(int n)
{
    cout << n << ' ';
}

class printObj
{
public:
    void operator()(int n)
    {
        cout << n << ' ';
    }
};

void add3(int& n)
{
    n += 3;
}

// 函数对象可以记录状态
class addObj
{
public:
    addObj(int num) : num_(num)
    {

    }
    void operator()(int& n)
    {
        n += num_;
    }
private:
    int num_;
};

class greaterObj
{
public:
    greaterObj(int num) : num_(num)
    {

    }
    bool operator()(int n)
    {
        return n > num_;
    }
private:
    int num_;
};
int main() {
    int a[] = {1, 2, 3, 4, 5};
    vector<int> v(a, a + 5);

    for_each(v.begin(), v.end(), PrintFun);
    cout << endl;

    // PrintFun也可以用函数对象实现
    for_each(v.begin(), v.end(), printObj());
    cout << endl;

    for_each(v.begin(), v.end(), add3);
    for_each(v.begin(), v.end(), PrintFun);
    cout << endl;

    // add3也可以用函数对象实现
    for_each(v.begin(), v.end(), addObj(10));
    for_each(v.begin(), v.end(), PrintFun);
    cout << endl;

    // 用count_if找到比n大的个数
    cout << count_if(a, a + 5, greaterObj(3)) << endl;
    return 0;
}

// 输出
1 2 3 4 5
1 2 3 4 5
4 5 6 7 8
14 15 16 17 18
2

5、STL中内置的函数对象

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值