栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

关于c++使用std::thread创建带缺省参数的线程问题

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于c++使用std::thread创建带缺省参数的线程问题

关于c++使用std::thread创建带缺省参数的线程问题
  • 起因
  • 问题
  • 问题原因
  • 解决方案
  • 附

起因

线程创建的主体是函数,现在创建一个带缺省参数的函数,再用来创建线程

// void* lpParam 传递this指针
// WPARAM wpParam 传递的参数
void Run(void* lpParam, WPARAM wpParam = NULL)
{...}
	std::thread* hThread = new std::thread(Run, std::move(this), 1);

当然这样是对的,编译可以通过,现在是以下代码有问题

	std::thread* hThread = new std::thread(Run, std::move(this));
问题
错误	C2672	“std::invoke”: 未找到匹配的重载函数
错误	C2893	未能使函数模板“unknown-type std::invoke(_Callable &&,_Types &&...) noexcept()”专用化
问题原因

首先想当然的认为std::thread不认识这个缺省函数,意味着std:thread不能补充缺省参数
那就先看看std::thread的construct

	thread() noexcept
		{	// construct with no thread
		_Thr_set_null(_Thr);
		}

	template>, thread>>>
		explicit thread(_Fn&& _Fx, _Args&&... _Ax)
		{	// construct with _Fx(_Ax...)
		_Launch(&_Thr,
			_STD make_unique, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
		}

重点看第二个construct函数
先直接看主体参数部分

// class _Fn 函数
// class... _Args 可变参数
explicit thread(_Fn&& _Fx, _Args&&... _Ax)

单就可变参数这一项似乎就与缺省参数存在冲突
再看函数主体流程

		_Launch(&_Thr,
			_STD make_unique, decay_t<_Args>...> >(
				_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...));
		
		-->调用_Launch函数
		
		template inline
			void _Launch(_Thrd_t *_Thr, _Target&& _Tg)
			{	// launch a new thread
			_LaunchPad<_Target> _Launcher(_STD forward<_Target>(_Tg));
			_Launcher._Launch(_Thr);
			}

		-->调用_Launcher._Launch函数
	
		void _Launch(_Thrd_t *_Thr)
			{	// launch a thread
			_Thrd_startX(_Thr, _Call_func, this);
			while (!_Started)
				_Cnd_waitX(_Cond, _Mtx);
			}

		-->调用_Thrd_startX使用底层的_Thrd_start创建线程,这里直接看调用函数处理部分
		
		static unsigned int __stdcall _Call_func(void *_Data)
			{	// entry point for new thread
			static_cast<_Pad *>(_Data)->_Go();
			return (0);
			}

		-->调用_Go下调用_Run(this)

		static void _Run(_LaunchPad *_Ln) noexcept	// enforces termination
			{	// construct local unique_ptr and call function object within
			_Target _Local(_STD forward<_Target>(_Ln->_MyTarget));
			_Ln->_Release();
			_Execute(*_Local,
				make_index_sequence>());
			_Cnd_do_broadcast_at_thread_exit();
			}

		-->这里再调用_Execute

		template
			static void _Execute(typename _Target::element_type& _Tup,
				index_sequence<_Idxs...>)
			{	// invoke function object packed in tuple
			_STD invoke(_STD move(_STD get<_Idxs>(_Tup))...);
			}

现在找到了源头再去回溯
倒数第二步

			_Execute(*_Local,
				make_index_sequence>());

这里是对可变参数进行整数化序列,现在就相当于对之前的

// void* lpParam 传递this指针
// WPARAM wpParam 传递的参数
void Run(void* lpParam, WPARAM wpParam = NULL)
{...}

参数整数化序列,这里应该有两个
而在编译期间

	std::thread* hThread = new std::thread(Run, std::move(this));

提供的数量只有一个,所以报错,这里实际上的结果是对函数参数的左值进行序列,而对右值不序列,所以导致这里编译报错;而根本原因可能还是

// class _Fn 函数
// class... _Args 可变参数
explicit thread(_Fn&& _Fx, _Args&&... _Ax)

可变参数无法进行缺省化,想到python的参数就可以可变且可省,只是速度有点慢罢了。

解决方案

既然可变无法缺省,那么就不使用缺省,改为

// void* lpParam 传递this指针
// WPARAM wpParam 传递的参数
void Run(void* lpParam, WPARAM wpParam)
{...}
	std::thread* hThread = new std::thread(Run, std::move(this), 1);

如果有多个,就都必须给出参数具体的值,比如接下来

	std::thread* hThread1 = new std::thread(Run, std::move(this), 2);

虽然感觉有点麻烦,但还是这样吧。

附

头文件

#include 

跟踪路径


-->

-->

底层的

_CRTIMP2_PURE void __cdecl _Thrd_abort(const char *);
_CRTIMP2_PURE int __cdecl _Thrd_start(_Thrd_imp_t *, _Thrd_callback_t, void *);

应该是闭源的

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1026825.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号