bind

昨天有粉丝问我,bind1st和bind有啥区别?今天就来简单讲讲。

bind1st和bind2nd在STL中主要用于二元函数对象,将其中的一元绑定成一个固定的量,成为一元函数变量。
在C++11标准中,这两位因为不够灵活,所以已经被bind所取代。

bind起源于非标准boost库,在c++11标准中正式纳入标准库,其更加灵活,最多可以绑定20个函数对象的参数。

bind的用法

先随便整上点函数:

void hello(string str) { cout << str << endl; }

int sum(int a, int b) { return a + b; }

class Test
{
public:
	int sum(int a, int b) { return a + b; }
};

然后再来看bind的实际应用:

int main()
{
	// bind是函数模板 可以自动推演模板类型参数
	bind(hello, "hello bind!")()//result:print:hello bind!
	cout << bind(sum, 10, 20)() << endl;//result:print:30
	cout << bind(&Test::sum, Test(), 20, 30)() << endl;//result:print:50
	// 参数占位符 绑定器出了语句,无法继续使用
	bind(hello, _1)("hello bind 2!");
	cout << bind(sum, _1, _2)(200, 300) << endl;//result:print:500
	return 0;
}

在语句bind(hello, "hello bind!")();中,bind将“hello bind!”绑定至hello的string类型参数,并返回一个函数对象,调用这个函数对象的operator()函数,完成打印字符串的过程。

在语句bind(hello, _1)("hello bind 2!");中的_1是名称空间 placeholders中的,用法placeholder::_1
此为参数占位符,代表hello的第一个参数等待用户输入。在本例中将参数“hello bind 2!”传递给operator()函数完成调用。

用function实现对bind绑定的函数对象的类型保留

bind有个缺点,不知道大家发现了没有。
bind无法保存它所绑定过的函数对象!

所以就需要function和它进行配合。

int main()
{
	function<void(string)> func1 = bind(hello, _1);
	func1("hello china!");
	func1("hello shan xi!");
	func1("hello si chuan!");

	return 0;
}

bind 和function实现线程池(假)

先把线程类定义好:

// 线程类
class Thread
{
public:
	Thread(function<void(int)> func, int no) :_func(func), _no(no) {}
	//这里需要包含头文件#include<thread>
	thread start()
	{
		//定义线程t执行func函数
		thread t(_func, _no); // _func(_no)
		return t;
	}
private:
	function<void(int)> _func;//接收绑定器返回的函数对象
	int _no;//线程编号
};

再定义好线程池类:

// 线程池类
class ThreadPool
{
public:
	ThreadPool() {}
	~ThreadPool()
	{
		// 这里是指针,所以不能依靠vector析构自动析构,得手动释放Thread对象占用的堆资源
		for (int i = 0; i < _pool.size(); ++i)
		{
			delete _pool[i];
		}
	}
	// 开启线程池
	void startPool(int size)
	{
		for (int i = 0; i < size; ++i)
		{
			_pool.push_back(
				new Thread(bind(&ThreadPool::runInThread, this, _1), i));
		}

		//执行线程函数
		for (int i = 0; i < size; ++i)
		{
			_handler.push_back(_pool[i]->start());
		}

		for (thread &t : _handler)
		{
			//等待线程执行完毕
			t.join();
		}
	}
private:
	vector<Thread*> _pool;
	vector<thread> _handler;

	// 把runInThread这个成员方法充当线程函数 thread pthread_create
	void runInThread(int id)
	{
		cout << "call runInThread! id:" << id << endl;
	}
};

应用:

int main()
{
	ThreadPool pool;
	pool.startPool(10);//创建10个线程
	return 0;
}
#endif

这里只是个概念模型,用还是用不了的。

参考文献

[1] 施磊.腾讯课堂——C++高级.图论科技,2020.7.