程序开发基础学习三(boost::bind 函数学习)

        工作中要用到boost库,我的学习习惯是在学习新的知识的时候,将整个知识点的历史和发展现状过一遍。这样既能激发学习兴趣,同时对于知识点的记忆和学习能形成一个完整的系统结构。boost库最新版本是1.47,今天主要总结boost库里一个常用的函数bind,由于之前从来没有用过这个函数,对这个函数的一些妙用也不甚了解。

        我对bind函数的理解是,bind现在最大支持九个参数,通过对bind传递不同的参数,最后返回一个新的函数指针,通过这个函数指针的调用变相的产生的函数。我先用普通方法简单模拟一下,大概说明白bind 的原理就行。代码如下:

#include "stdafx.h"
#include <iostream>
#include "boost/bind.hpp"
#include "boost/function.hpp"
using namespace std;


void PrintHello(int i)
{
        cout<<"hello, world.\n";
}
void CallFuntion(void (*f)(int), int i)
{
        f(i);
}


int _tmain(int argc, _TCHAR* argv[])
{
       CallFuntion(PrintHello, 2);
       getchar();
       return 0;
}

        这个就是通过传递函数PrintHello的函数指针给CallFuntion函数,当然了,有人说直接调用PrintHello多省事,呵呵,说的没错,看看下面bind的几种用法吧。

        1、bind构造普通函数

#include "stdafx.h"
#include <iostream>
#include "boost/bind.hpp"
#include "boost/function.hpp"
using namespace std;

void PrintHello(int i)
{
	cout<<"hello, world.\n";
}
void CallFuntion(void (*f)(int), int i)
{
	f(i);
}

void CallBindFunction(boost::function<void (void)> f)
{
	f();
}
int _tmain(int argc, _TCHAR* argv[])
{
	CallFuntion(PrintHello, 2);
	CallBindFunction(boost::bind(PrintHello, 2));
	getchar();
	return 0;
}

        看见区别了吧,通过配合boost里的function函数,不就可以实现函数变参了,这就是bind的一种妙用。

         2、bind函数调整参数

#include "stdafx.h"
#include <iostream>
#include "boost/bind.hpp"
#include "boost/function.hpp"
using namespace std;


int Sum2(int i, int j)
{
	return i + j;
}


int _tmain(int argc, _TCHAR* argv[])
{
	cout<<Sum2(1, 2)<<endl;	// Sum2(x, y);

	boost::function<int (int, int)> f11 = boost::bind(Sum2, _1, _1);     // Sum2(x, x);

	cout<<f11(1, 2)<<endl;
	boost::function<int (int, int)> f21 = boost::bind(Sum2, _2, _1);	 // Sum2(y, x);
	cout<<f21(1, 2)<<endl;

	boost::function<int (int, int)> f12 = boost::bind(Sum2, _2, _2);     // Sum2(y, y);
	cout<<f12(1, 2)<<endl;

	boost::function<int (int, int)> f13 = boost::bind(Sum2, _1, 3);		// Sum2(x, 3);
	cout<<f13(1, 2)<<endl;
	getchar();
	return 0;
}


        这就是通过bind函数构造出不同参数的函数,是不是大大加大了代码的复用性和易用性。同时可以在bind的参数里设置构造的新函数默认值。

        3、函数对象

#include "stdafx.h"
#include <iostream>
#include "boost/bind.hpp"
#include "boost/function.hpp"
#include "boost/ref.hpp"
using namespace std;

struct F
{
	int s;
	int operator()(int i){ return s += i;}
	bool operator()(bool b){ return b;}
};

int _tmain(int argc, _TCHAR* argv[])
{
	F f = {0};
	int arry[3] ={1, 2, 3};
	//boost::function<int (int)> sum = boost::bind(boost::ref(f), _1);
	boost::function<int (int)> sum = boost::bind<int>(boost::ref(f), _1);
	for_each(arry, arry + 3, sum);
	assert(f.s != 6);
	return 0;
}

         这里有两个知识点,一个是bind构造的函数要表明返回类型,boost文档给出的解释是: 没有 typeof操作符,返回类型无法推导。其实我们自己也很容易看出来,对于上面申明的两个操作符重载,没有返回类型确实无法分辨。第二个知识点是,引用的问题,假如不添加引用符号ref的话,默认会复制一个新的函数对象,这样的话,前面定义的f的s值不会改变。

        4、成员函数

#include "stdafx.h"
#include <iostream>
#include "boost/bind.hpp"
#include "boost/function.hpp"
#include "boost/ref.hpp"
#include "boost/shared_ptr.hpp"
using namespace std;

struct X
{
	void f(int count)
	{
		for (int i = 0; i < count; ++i)
		{
			cout<<"hello,world.\n";
		}
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	X x;
	boost::shared_ptr<X> p(new X);

	boost::function<void (int)> PrintHello1 = boost::bind(&X::f, boost::ref(x), _1); // x.f(i)
	PrintHello1(1);

	boost::function<void (int)> PrintHello2 = boost::bind(&X::f, &x, _1);	// (&x)->f(i)
	PrintHello2(2);

	boost::function<void (int)> PrintHello3 = boost::bind(&X::f, x, _1);	// (internal copy of x).f(i)
	PrintHello2(3);

	boost::function<void (int)> PrintHello4 = boost::bind(&X::f, p, _1);	// (internal copy of p).f(i)
	PrintHello2(4);
	return 0;
}

        这里注意的是第三种方式和第四种方式,第三种方式里的x将被拷贝,如果x数据结构比较大的话,效率上讲就非常低了,需要注意。第四种也是拷贝,但这里还申明为shared_ptr类型,意思是在出了限定域内不会释放,这boost文档里给出的例子。没有别的意思,就是见到后注意下就行。

        bind基本就这几种用法,还有一些比较巧妙的用法,比如说将bind返回值当作参数传递给bind嵌套用法,还有将function<void (void)> 类型申明为成员函数。有兴趣的话可以看boost文档,或者九天翱雁的关于bind的用法总结。

你可能感兴趣的:(程序开发基础学习三(boost::bind 函数学习))