zoukankan      html  css  js  c++  java
  • 程序开发基础学习三(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的用法总结。

  • 相关阅读:
    arcgis10.2转shp文件中文乱码问题解决方案
    Android Context作为参数传递this
    andriod inputbox
    andriod inputType
    《ArcGIS Runtime SDK for Android开发笔记》——(5)、基于Android Studio构建ArcGIS Android开发环境(离线部署)(转)
    终于理解了什么是LGPL
    产品经理如何与强势的技术沟通? 技术比较有资历,会以技术无法实现等方面的原因拒绝处理产品提出的需求。 你们是否遇到这样的技术? 产品懂技术的话,是不是会好一些,因为可以和技术说“行话”了,并且产品懂技术就不会被忽悠了。
    Core Dump总结
    LIBRARY_PATH是编译时候用的,LD_LIBRARY_PATH是程序运行是使用的
    如何禁止C++默认成员函数
  • 原文地址:https://www.cnblogs.com/fengju/p/6174341.html
Copyright © 2011-2022 走看看