C++ Thread , ref相关:https://genbattle.bitbucket.io/blog/2016/05/29/Passing-References-to-Deferred-Function-Calls-with-std-ref/
#include <thread> #include <iostream> void start_thread(int& param) { std::cout << param << std::endl; } int main() { int value(7); std::thread mythread(start_thread, value); mythread.join(); return 0; }
乍看之下,有一个“引用包装器”,而不是一个普通的旧引用似乎没有什么用处。 它的直接用处被这样一个事实所掩盖:它只有在使用像C ++ 11一样添加的其他新特性(如std::bind
和std::thread
)时才真正有用。 std::ref
是一种解决方法,用于模板类型推导规则推导参数类型的情况,以便参数按值取值,而意图是通过引用来取参数。
报错信息类似:
In file included from /usr/include/c++/5.3.0/thread:39:0, from main.cpp:1: /usr/include/c++/5.3.0/functional: In instantiation of ‘struct std::_Bind_simple<void (*(int))(int&)>’: /usr/include/c++/5.3.0/thread:137:59: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(int&); _Args = {int&}]’ main.cpp:11:45: required from here /usr/include/c++/5.3.0/functional:1505:61: error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’ typedef typename result_of<_Callable(_Args...)>::type result_type; ^ /usr/include/c++/5.3.0/functional:1526:9: error: no type named ‘type’ in ‘class std::result_of<void (*(int))(int&)>’ _M_invoke(_Index_tuple<_Indices...>) ^
忽略这里明显的设计缺陷; 这个例子只是为了演示当你尝试传递一个值参数时引用从std::thread::thread()
等模板函数调用的函数时会发生什么。 请注意,模板类型推导(正确)推导值的类型为int
,但这不符合它在start_thread中看到的int&
类型。 编译器给出的实际错误(在这种情况下为GCC)实际上比这更为模糊:
编译器确实表明,错误隐约与将函数参数绑定到传入的函数有关; 使用指向std::ref
的错误中的关键字作为解决方案进行在线快速搜索。
那么std::ref
如何通过引用将参数传递给参数类型按值推导的模板函数?std::reference_wrapper
(由std::ref
返回的类型)及其libstdc ++ 文档 / 源代码的定义描绘了一幅非常清晰的图片。 std::reference_wrapper
只是一个隐式地转换为引用的指针的薄包装(通过operator T&() const
):
所以模板函数中参数的推导类型是std::reference_wrapper<T>
(在上面的例子中是std::reference_wrapper<int>
),它可以通过值传递给函数。 这与参考大小相同,当它传递给另一个需要参数的函数时,它会隐式转换为一个参数。 所以在功能上,它闻起来很像一个参考。 让我们看看它的行动:
#include <thread> #include <iostream> #include <functional> void start_thread(int& param) { std::cout << param << std::endl; } int main() { int value(7); std::thread mythread(start_thread, std::ref(value)); mythread.join(); return 0; }
output:7