存档在 ‘boost.bind’ 分类

boost::bind不同参数形式性能分析

2014年4月16日

boost::bind针对于值,引用,指针提供了统一的语法使用,可以利用这一特点,简化编码,来看下面的代码:

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <iostream>

class A
{
public:
	A(){std::cout<<"A构造函数"<<std::endl;}
	A(const A& a) {std::cout<<"A拷贝构造函数"<<std::endl;}
	A& operator=(const A& a){std::cout<<"A赋值函数"<<std::endl;}
	~A(){std::cout<<"A析构函数"<<std::endl;}
	void printA(){}
};

int _tmain(int argc, _TCHAR* argv[])
{
	{
		A a;
		boost::bind(&A::printA, a)(); //1
		boost::bind(&A::printA, boost::ref(a))();//2
		boost::bind(&A::printA, &a)();//3
	}
	system("pause");;
	return 0;
}

使用1的时候,有多次的拷贝构造函数调用,因为bind是值语义的。

使用2,3的时候,则对A的对象只有一次构造和一次析构。

大约可以得出:在类A拷贝比较复杂或者耗时的情况下,最好还是使用引用或者指针方式传递。否则还是以值语义来传递。

boost::bind应用分析

2014年4月9日

本文主要从应用角度讨论boost::bind,源码级别的分析以后有空再写写,这里不得不称赞boost::bind比起C++标准库的bind1st,bind2nd来说,支持的参数更多,使用也更简单,另外我觉得最好还是对泛型模板编程有一定了解,对C++标准库实现有了解。

1.自由函数,bind参数个数为自由函数参数个数+1

void func_void_int_int(int a, int b)
{
	cout << "自由函数func_void_int_int " <<a<<"   "<<b<< endl;
}

该自由函数返回为void,参数分别为int,int,使用bind也很简单。

	boost::bind(&func_void_int_int,3,4)();
	boost::bind(&func_void_int_int,3,_1)(4);
	boost::bind(&func_void_int_int,_1,_2)(5,6);
	boost::bind(&func_void_int_int,_1,_1)(7);

其中用了_1,_2占位符,而且还可以使用延迟指定参数。

2.函数对象(仿函数),bind参数个数为operator参数个数+1

class FuncObject_void_int
{
public:
	void operator()(int x)
	{
		cout<<"函数对象FuncObject_void_int "<<x<<endl;
	}
};

这个仿函数返回值为void,参数为int,在使用bind时,需要指定模板参数。

boost::bind<void>(FuncObject_void_int(), 4)();
boost::bind<void>(FuncObject_void_int(), _1)(4);

这里需要指定仿函数的返回值作为bind的模板形参,因为函数的参数都可以根据传进来的值进行推断,返回值则推断不了。

再来看看其他返回值情况

class FuncObject_int_int
{
public:
	int operator()(int x)
	{
		cout<<"函数对象FuncObject_int_int "<<x<<endl;
		return x;
	}
};
int answer = boost::bind<int>(FuncObject_int_int(), 10)();

3.继承自标准库的仿函数,bind参数个数为operator参数个数+1

class FuncObjectDerived_void_int : public unary_function<int, void>
{
public:
	void operator()(int x)
	{
		cout<<"函数对象FuncObjectDerived_void_int "<<x<<endl;
	}
};
class FuncObjectDerived_int_int_int : public  binary_function<int, int, int>
{
public:
	int operator()(int x,int y)
	{
		cout<<"函数对象FuncObjectDerived_int_int "<<x<<" "<<y<<endl;
		return x + y;
	}
};

这里使用继承了标准库的unary_function与binary_function,如果不知道这两个是干什么的,最好还是去看看文末尾给出的一些书籍。

当使用这两个函数对象时,不再需要模板参数了,因为通过他们的父类就可以获得

	boost::bind(FuncObjectDerived_void_int(), 11)();
	answer = boost::bind(FuncObjectDerived_int_int_int(), _1, _2)(13, 14);

4.类的非静态成员函数,bind参数个数为成员函数参数个数+2

第一个参数为成员函数指针,第二个参数表明绑定到this的对象,其他为参数

class ClassTest
{
public:
	ClassTest(int _a):a(_a){}
	void printA(int x)
	{
		cout<<"输出A x "<<a<<"  "<<x<<endl;
	}
	int getAB(int b)
	{
		cout<<"获得AB "<<a*b<<endl;
		return a;
	}
private:
	int a;
};

使用规则如下,这个时候就体现出了boost的强大特性,以不变应万变:

	ClassTest myClassTest(88);
	boost::bind(&ClassTest::printA, myClassTest,_1)(77);

	ClassTest* pClassTest = &myClassTest;
	boost::bind(&ClassTest::printA, pClassTest,_1)(88);

	boost::shared_ptr<ClassTest> spClassTest(new ClassTest(88));
	boost::bind(&ClassTest::printA, spClassTest, _1)(99);

5.参考文献

<超越C++标准库 boost库导论>

<STL源码剖析>

<C++标准程序库>

<泛型与模板编程>

源码:testBootst