函数对象

函数对象

传递给算法的函数型参数并不一定是函数,也可能是类似函数的对象。这种对象称为函数对象,或者称为仿函数。

定义一个函数对象

任何东西,只要其行为像函数,那么它就是一个函数。因此你定义了一个对象,行为像函数,它就可以被当作函数使用。也就说它具备着函数行为。什么叫函数行为:使用小括号传递参数,借以调用某个东西。

function(arg1, arg2);

如果希望一个对象也能这样使用,那么就必须让它也有可能被调用,通过小括号的运用和实参的传递。那么就需要定义operator(),并给予合适的参数类型。

class X
{
public:
	//define "function call" operator
	return-value operator() (arguments) const;
};

那么,你现在可以把X的对象当作函数来使用了

X fo;
fo(arg1, arg2);
//等价与
fo.operator()(arg1, arg2);

下面是一个完整的例子

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

class PrintInt
{
public:
	void operator()(int elem) const
	{
		cout << elem << " ";
	}
};

int main()
{
	vector<int> coll{1,2,3,4,5,6};
	for_each(coll.begin(), coll.end(), PrintInt());
}

注意:for_each的最后一个参数PrintInt()的作用是创建一个临时对象作为for_each的一个参数

//for_each的算法大致如下
namespace std
{
	template <typename Iterator, typename Operation>
	Operation for_each(Iterator act, Iterator end, Operator op)
	{
		while (act != end)
		{
			op(*act);
			++act;
		}
		return op;
	}
}

函数对象的优势:

  • 函数对象是一种带状态的函数(可以拥有成员函数和成员变量,承载信息更多)
  • 一个template的类,根据不同的类型,可以生成不同的类型,不同的对象,代码量比函数少
  • 速度快,很多细节在编译期就确定了,可能得到更好的优化

比如,对于第一个优势

class AddValue
{
public:
	AddValue(int v) : _value(v){}
	void operator()(int &elem) const
	{
		elem += _value;
	}
private:
	int _value;
};

list<int> coll{1,2,3,4,5,6,7};
for_each(coll.begin(), coll.end(), AddValue(10));

STL标准库里面有很多自定义的函数对象

#include <functional>//自定义函数对象的头文件
set<int, less<int> > coll;
set<int, greater<int>> coll;
transform(coll.begin(), coll.end(), negate<int>());
//...
Binder,可以将预定义的函数对象和其他数值结合
#include <iterator>
#include <functional>
#include <set>
#include <deque>
#include <algorithm>
#include <iostream>

using namespace std;
int main()
{
	set<int, greater<int>> coll{1,2,3,4,5,6,7};
	deque<int> coll2;
	transform(coll.begin(), coll.end(), 
		back_inserter(coll2), 
		bind(multiplies<int>(),_1,10));
	replace_if(coll2.begin(), coll2.end(),
		bind(equal_to<int>(), _1, 70),
		34);
	return 0;
}

对于bind(multiplies(),_1,10),定义一个函数对象,并将第一个参数乘以10

auto f = bind(multiplies<int>(), _1, 10);
cout << f(99) << endl;

也可以和自定义的函数对象结合

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>

using namespace std;
using namespace std::placeholders;

template <typename T>
class MyEqual
{
public:
	bool operator()(T a, T b)
	{
		return a == b;
	}
};

int main(int argc, char* argv[])
{
    vector<int> a{1,2,3,4,5,6,7};
    auto count = count_if(a.begin(), a.end(), bind(MyEqual<int>(), _1, 1));

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值