C++11标准库thread构造函数浅析

181 阅读2分钟

一、标准库Thread内容(函数内部实现内容已摘去)

class thread
	{	// class for observing and managing threads
public:
	class id;
	typedef void *native_handle_type;
	thread() noexcept;
	template<class _Fn,
		class... _Args,
		class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
		explicit thread(_Fn&& _Fx, _Args&&... _Ax)
		{	// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
		}
	~thread() noexcept;
	thread(thread&& _Other) noexcept
		: _Thr(_Other._Thr);
	thread& operator=(thread&& _Other) noexcept;
	thread(const thread&) = delete;
	thread& operator=(const thread&) = delete;
	void swap(thread& _Other) noexcept;
	_NODISCARD bool joinable() const noexcept;
	void join();
	void detach();
	_NODISCARD id get_id() const noexcept;
	_NODISCARD static unsigned int hardware_concurrency() noexcept;

	_NODISCARD native_handle_type native_handle();

private:
	thread& _Move_thread(thread& _Other);
	_Thrd_t _Thr;
	};

二、Thread类简单介绍

在介绍那个很复杂的构造函数前我们大致了解一下该类。

1、以下含义为thread被创建出来后不能进行拷贝和拷贝赋值,但是有move语义(c++11重要特性)。

thread(thread&& _Other) noexcept
	: _Thr(_Other._Thr);
thread& operator=(thread&& _Other) noexcept;
thread(const thread&) = delete;
thread& operator=(const thread&) = delete;
void swap(thread& _Other) noexcept;

2、常用接口(不是本篇的主题,将在另外文章中讲到,请参考blog.csdn.net/qq_43148810…

void join();
void detach();
_NODISCARD id get_id() const noexcept;
_NODISCARD static unsigned int hardware_concurrency() noexcept;

三、复杂而重要的构造函数(本文的主题)

template<class _Fn,
		class... _Args,
		class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>
		explicit thread(_Fn&& _Fx, _Args&&... _Ax)
		{	// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
		}

1、模板参数部分

template<class _Fn,
		class... _Args,
		class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>>

1)class _Fn是设想匹配的是可调用对象(函数、成员函数、函数对象、lambda表达式)等。 2)class... _Args,匹配可调用对象的参数列,为C++11的重要特性Variadic Templates(...)和元组tuple。 3)以下内容我们由内到外一层一层分析(对萃取机和元编程要稍作了解)

class = enable_if_t<!is_same_v<remove_cv_t<remove_reference_t<_Fn>>, thread>>

a、remove_reference_t<_Fn>为退化_Fn的引用和右值引用。 b、remove_cv_t<#a#>在a的基础上再退化_Fn的const和volatile c、is_same_v<#b#, thread>在b的基础上判断_Fn和thread是否为同种类型。 d、enable_if_t<!#c#>若c的结果为false则该构造函数模板匹配成功,否则失败。 e、class=#d#为匿名模板参数,并且没有占位(一般匿名形参占位来重载) 小结:这么一大串是为了不和其他构造发生二义性,使得“1)”中_Fn为可调用对象的设想为真,而不是线程对象。 不同版本VS源码稍有差别,核心思想不会变。

四、延伸探讨

// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique<tuple<decay_t<_Fn>, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));

该构造函数的实现部分有兴趣的也可以研究研究。

如有错误或不足欢迎评论指出!创作不易,转载请注明出处。如有帮助,记得点赞关注哦(⊙o⊙) 更多内容请关注个人博客:juejin.cn/creator/hom…