一. 声明及使用
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);