仿函数与临时对象

原创 2015年11月18日 13:11:41

仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
所谓临时变量,就是一种无名对象。有的时候可以制造一些临时对象,可以使程序干净清爽。可以制造临时对象的方法是,在类别名称之后直接加一对小括号,并可指定初值,其意义相当于调用相应的constructor且不指定对象名称。STL最常将此技巧应用于仿函数与算法的搭配上。

见下面例子:

#include <iostream>  
#include <algorithm>
#include <vector>
using namespace std;

template<typename T>
class print
{
public:
	void operator()(const T&elem)  //重载()
	{
		cout << elem << " ";
	}
};

int main()
{
	int ia[6] = { 0, 1, 2, 3, 4, 5 };
	vector<int> iv(ia,ia+6);
	for_each(iv.begin(), iv.end(), print<int>());
	cout << endl;
}

下面比较使用一般函数和使用仿函数:

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

using namespace std;

template<class T>
inline void PRINT_ELEMENTS(const T& coll,const char * optcstr="")
{
	typename T::const_iterator pos;
	cout<<optcstr;
	for(pos=coll.begin();pos!=coll.end();++pos)
	{
		cout<<*pos<<" ";
	}
	cout<<endl;
}

int square(int value)
{
	return value*value;
}

template<int theValue>
void add(int &elem)
{
	elem+=theValue;
}

int main()
{
	vector<int> coll1;
	vector<int> coll2;

	for(int i=1;i<=9;i++)
	{
		coll1.push_back(i);
	}
	PRINT_ELEMENTS(coll1,"initialized: ");

	for_each(coll1.begin(),coll1.end(),add<10>);

	PRINT_ELEMENTS(coll1,"after adding 10: ");

	transform(coll1.begin(),coll1.end(),back_inserter(coll2),square);

	PRINT_ELEMENTS(coll2,"squared: ");

	system("pause");
	return 0;
}


#include<iostream>
#include<list>
#include<algorithm>

using namespace std;

template<class T>
inline void PRINT_ELEMENTS(const T& coll,const char * optcstr="")
{
	typename T::const_iterator pos;
	cout<<optcstr;
	for(pos=coll.begin();pos!=coll.end();++pos)
	{
		cout<<*pos<<" ";
	}
	cout<<endl;
}

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

int main()
{
	list<int> coll;

	for(int i=1;i<=9;i++)
	{
		coll.push_back(i);
	}

	PRINT_ELEMENTS(coll,"initialized: ");

	for_each(coll.begin(),coll.end(),AddValue(10));

	PRINT_ELEMENTS(coll,"after adding 10: ");

	for_each(coll.begin(),coll.end(),AddValue(*coll.begin()));

	PRINT_ELEMENTS(coll,"after adding first element: ");

	system("pause");
	return 0;
}

凡是行为像函数,那么这个对象就是函数。仿函数就是这个意思,但是STL中为什么要用仿函数而不直接用函数呢?

首先STL是一个有自己规则的框架,函数指针无法和STL其他组件搭配(配接器),产生更灵活的变化:

仿函数应当有能力被函数配接器修饰,然后彼此合作形成一个整体。为了可配接仿函数需要定义自己的相应型别(和迭代器的型别的作用是一个含义)。由于STL只使用一元和二元仿函数,所以定义了两个class:unaru_function和binary_function。这两个类没有成员,只有一些型别定义。任何仿函数,只要依个人需求选择继承其中一个class,便自动拥有了那些相应型别,也就自动拥有了配接能力。

其次仿函数相对于函数指针有其自身优点:

1、 仿函数是智能型函数

就好比智能指针的行为像指针,其就可看作是一个指针。但是智能指针是定义的一个类对象,所以在具备指针功能的同时也有其他的能力。仿函数的能力也可以超越operator()。因为仿函数可以拥有成员函数和成员变量,这意味着仿函数拥有状态。另一个好处是可以在执行期初始化它们。

2、 仿函数都有自己的型别

这就是泛型编程编写仿函数。

3、 仿函数通常比一般函数快

就template的概念而言,由于更多细节在编译器就已确定,所以通常可能进行更好的最佳化。


版权声明:本文为博主原创文章,未经博主允许不得转载。

临时对象的产生和运用以及仿函数的用法

临时对象即无名对象。如果临时对象的出现不在程序员的预期之下,则会造成效率上的负担。而有时候,刻意制造的临时对象又使得程序看起来简洁明快。STL最常将此算法应用于仿函数和算法的搭配上。如(摘抄于STL源...

关于析构函数和临时对象的问题

  • 2008年07月20日 13:37
  • 32KB
  • 下载

[渡一] 171108 构造函数、包装类、临时对象、原型

笔记

C++中的临时对象(拷贝构造函数)

我们知道在C++的创建对象是一个费时,费空间的一个操作。有些固然是必不可少,但还有一些对象却在我们不知道的情况下被创建了。通常以下三种情况会产生临时对象:   1,以值的方式给函数传参; ...

C++中的临时对象(拷贝构造函数)(上)

C++中的临时对象(拷贝构造函数)(上) 2010-09-10 11:25:03 分类: C/C++ 我们知道在C++的创建对象是一个费时,费空间的一个操作。有些固...

C++中的临时对象(拷贝构造函数)(下)

三,函数返回一个对象。     当函数需要返回一个对象,他会在栈中创建一个临时对象,存储函数的返回值。看以下代码: view plain #include   ...
  • icycode
  • icycode
  • 2011年08月31日 20:08
  • 462

重点介绍了复制构造函数, 直接初始化,复制初始化,赋值,临时对象之间的关系,本文内容全面,简单易懂

本文作者:黄邦勇帅 本文是学习 C++中的最基本的内容,因此学习 C++就应全部掌握本文的内容。在知道了怎样声明一个类之后,就会遇到 关于构造函数的问题,本文是关于构造函数的专题,集中介绍了默认构...

C++中的临时对象(拷贝构造函数)(上)

我们知道在C++的创建对象是一个费时,费空间的一个操作。有些固然是必不可少,但还有一些对象却在我们不知道的情况下被创建了。通常以下三种情况会产生临时对象:   1,以值的方式给函数传参;   2,...
  • icycode
  • icycode
  • 2011年08月31日 20:06
  • 454

函数中的临时对象

#include "stdafx.h"#include using namespace std;  class Internet;Internet * pa;Internet * pb;class I...

C++调用函数是如何返回临时对象的

请看如下代码 #include "stdafx.h" #include using namespace std; class INT { friend ostream& operator...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:仿函数与临时对象
举报原因:
原因补充:

(最多只允许输入30个字)