C++STL仿函数

什么是仿函数

答:仿函数又叫函数对象,是一个定义了operator()的对象。你可以将仿函数视为一般函数,只不过不是将所有语句放在函数体里,而是放在operator()中撰写。

//例如
struct foo
{
	void operator()(int i)
	{
		cout << i;
	}
};

int main()
{
	int a[5] = { 1,2,3,4,5 };
	foo f;
	for (int i = 0; i < 5; i++)
		f(a[i]);
}
//输出12345

仿函数与一般函数相比优点在哪?

1:仿函数比一般函数更灵活,因为它可以有不同的状态。
2:每个仿函数都有其型别,所以我们可以将其当作模板参数来传递
3:执行速度上,仿函数通常比一般函数更快

//这里将展示 仿函数比一般函数更灵活的例子
//我们定义了一个仿函数和一个一般函数,让它们判断参数是否大于3
class foo
{
private:
	int value;
public:
	foo(int v = 0) :value(v) {}
	bool operator()(int i)
	{
		return i > value;
	}
};

bool fx(int i)
{
	return i > 3;
}

int main()
{
	int a[5] = { 1,2,3,4,5 };
	
	for (int i = 0; i < 5; i++)
	{
		if (fx(a[i]))
			cout << a[i] << " ";
	}cout << endl;

	for (int i = 0; i < 5; i++)
	{
	   //foo(3)(a[i])
	   //等价于 foo f(3) 
	   // f(a[i])
		if (foo(3)(a[i]))
			cout << a[i] << " ";
	}cout << endl;
    
    //如果我们将判断条件改成是否大于2
	for (int i = 0; i < 5; i++)
	{
		if (foo(2)(a[i]))
			cout << a[i] << " ";
	}cout << endl;
}


//我们可以很清楚的感受到仿函数比一般函数更灵活
//如果是一般函数只能在函数体修改判断条件

需要注意的一点是,仿函数以by value的方式传递,这样做的好处是你可以传递常量或者临时表达式。缺点是:你无法改变仿函数的状态,利用for_each()可以帮助我们保存仿函数的状态

//我们可以利用for_each()的返回值来保存仿函数的状态(value的值)
class foo
{
private:
	int value;

public:
	foo(int v = 0) :value(v) {}
	void operator()(int& i)
	{
		i+=value;
		value++;
	}
};


int main()
{
	vector<int>c1 = { 1,2,3 };
	vector<int>c2 = { 1,2,3 };
     foo fx=for_each(c1.begin(), c1.end(), foo(2));
	for (auto e : c1)  //3 5 7
		cout << e << ' ';
	cout << endl;  

	for_each(c2.begin(), c2.end(), fx);
	for (auto e : c2)  //6 8 10
		cout << e << ' ';
	cout << endl;
}

C++标准库预定义的仿函数

使用时需要包含头文件functional

表达式 功能
negate<>() -x
plus<>() x1+x2
minus<>() x1-x2
multiplies<>() x1*x2
divides<>()) x1/x2
modulus<>() x1%x2
equal_to<>() x1 == x2
not_equal_to<>() x1 !=x2
less<>() x1<x2
greater<>() x1>x2
less_equal<>() x1 <= x2
greater_equal<>() x1>=x2
logical_not<>() !x
logical_and<>() x1&&x2
logical_or<>() x1 或 x2

函数配接器(Function Adapters)

表达式 功能
bind1st(op,value) 将value绑定为op函数的第一参数
bind2dn(op,value) 将value绑定为op函数的第二参数
not1(op) 将op函数结果取反 ,op为判断函数,接受一个参数
not2(op) 将op函数结果取反 ,op为判断函数,接受两个参数

针对成员函数而设计的函数配接器

表达式 功能
mem_fun_ref(op) 调用op,那是某个对象的一个const成员函数
mem_fun(op) 调用op,那是某个对象指针的一个const成员函数

针对一般函数而设计的函数配接器

表达式 功能
ptr_fun(op) op(x)
//例如有这样一个一般函数
bool check()
{
.....
}

int main()
{
   find_if(c.begin(),c.end(),not1(ptr_fun(check)));
}

如何让自定义的仿函数可以使用函数配接器?

答:使用上述的ptr_fun(),或者让你自定义的仿函数继承unary_function或者binary_function具体继承那个类,取决你的仿函数是一元函数还是二元函数。

辅助用(组合型)的仿函数

答:即一些将几种仿函数结合在一起的函数配接器,我个人认为使用该配接器过于麻烦,可以使用C++11新特性中的lambada表达式来实现我们要的效果。如果该想法有误,请指正。

原创文章 23 获赞 1 访问量 360

猜你喜欢

转载自blog.csdn.net/weixin_44806268/article/details/105708352