您的位置:首页 > 理论基础 > 数据结构算法

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

2011-07-17 21:50 507 查看
by:武龙飞 工作中要用到boost库,我的学习习惯是在学习新的知识的时候,将整个知识点的历史和发展现状过一遍。这样既能激发学习兴趣,同时对于知识点的记忆和学习能形成一个完整的系统结构。boost库最新版本是1.47,今天主要总结boost库里一个常用的函数bind,由于之前从来没有用过这个函数,对这个函数的一些妙用也不甚了解。 我对bind函数的理解是,bind现在最大支持九个参数,通过对bind传递不同的参数,最后返回一个新的函数指针,通过这个函数指针的调用变相的产生新的函数。我先用普通方法简单模拟一下,大概说明白bind 的原理就行。代码如下:view plain#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构造普通函数view plain#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函数调整参数view plain#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、函数对象view plain#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、成员函数view plain#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的用法总结。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息