函数对象

一. 声明及使用

1. 不包含数据

Class MyFunctionObject
{
public:
    void operator()(int x)
    {
        ...
    }
}
myFunctionObject(x);

2. 包含数据

class MyFunctionObject
{
public:
    explicit MyFunctionObject(Data data) : data_(data) {}
    void operator()(int x)
    {
        ....usage of data_....
    }
private:
    Data data_;
}

    MyFunctionObject myFunctionObject(data);
    myFunctionObject(42);

3. lambda since C++11

Data data;
auto myFunctionObject = [data](int x) { ....usage of data_.... };
myFunctionObject(42);

二. 应用方法

    >Callables are used profusely with the STL because algorithms have generic behaviours that are customized by callables.

以for_each为例

  • 函数指针
void bump2(int& number)
{
    number += 2;
}
std::vector<int> number = {1, 2, 3, 4, 5};
std::for_each(number.begin(), numbers.end(), bump2);
  • 函数对象
class Bump
{
public:
    explicit Bump(int bumpValue) : bumpValue_(bumpValue) {}
    void operator()(int& number) const
    {
        number += bumpValue_;
    }
private:
    double bumpValue_;
};

std::vector<double> numbers = {1, 2, 3, 4, 5};
std::for_each(numbers.begin(), numbers.end(), Bump(2));
  • lambda
    std::vector<double> numbers = {1, 2, 3, 4, 5};
    int bumpValue = 2;
    std::for_each(numbers.begin(), numbers.end(), [bumpValue](int& number) { number += bumpValue; } );

以上展示了STL算法与函数对象(函数指针、lambda)结合使用的方法

for_each的可能实现

template<class InputIt, class UnaryFunction>
constexpr UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f){
    for (; first != last; ++first) {
        f(*first);
    }
    return f; // implicit move since C++11}

三. 最佳实践之避免在函数对象中保持状态

example: 计算集合numbers中数字是7的个数

  • 函数对象
class Count7
{
public:
    Count7() : counter_(0) {}
    void operator()(int number)
    {
        if (number == 7) ++counter_;
    }
    int getCounter() const 
    {
        return counter_;
    }
private:
    int counter_;
};
std::vector<int> numbers = {1, 7, 4 , 7, 7, 3, 2};
int count = std::for_each(numbers.begin(), numbers.end(), Count7()).getCounter();

思考下面的用法对么?

std::vector<int> numbers = {1, 7, 4, 7, 7, 2, 3, 4};
Count7 count7;
std::for_each(numbers.begin(), numbers.end(), count7);
int count = count7.getCounter();
  • lambda
std::vector<int> numbers = {1, 7, 4, 7, 7, 2, 3, 4};
int count = 0;
std::for_each(numbers.begin(), numbers.end(), [&count](int number) { if (number == 7) ++count; });

以上算法的选择在表达力上欠缺,相对难理解;一旦在函数对象里面保持状态,会增加对代码理解的复杂度

  • 选择更好的算法
std::vector<int> numbers = {1, 7, 4, 7, 7, 2, 3, 4};
int count = std::count(numbers.begin(), numbers.end(), 7);
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容