Pre*_*rag 38 c++ multithreading reference c++11 stdthread
这是一个例子:
#include<iostream>
#include<thread>
using namespace std;
void f1(double& ret) {
ret=5.;
}
void f2(double* ret) {
*ret=5.;
}
int main() {
double ret=0.;
thread t1(f1, ret);
t1.join();
cout << "ret=" << ret << endl;
thread t2(f2, &ret);
t2.join();
cout << "ret=" << ret << endl;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
ret=0
ret=5
Run Code Online (Sandbox Code Playgroud)
用gcc 4.5.2编译,有和没有-O2
标志.
这是预期的行为吗?
这个节目数据是否免费比赛?
谢谢
Max*_*kin 85
构造函数std::thread
推导出参数类型并按值存储它们的副本.这需要确保参数对象的生命周期至少与线程的生命周期相同.
C++模板函数参数类型推导机制T
从类型的参数中推导出类型T&
.所有参数std::thread
被复制,然后传递给线程函数,以便 f1()
和f2()
总是使用该副本.
如果您坚持使用引用,请使用boost::ref()
或包装参数std::ref()
:
thread t1(f1, boost::ref(ret));
Run Code Online (Sandbox Code Playgroud)
或者,如果您更喜欢简单,请传递指针.这是你在场后的表现boost::ref()
或std::ref()
做法.
在这些情况下你需要一个明确的std::ref()
(或boost::ref()
)实际上是一个非常有用的安全功能,因为传递引用本质上是一件危险的事情.
使用非const引用时,通常存在传递局部变量的危险,使用const引用它可能是临时的,并且当您创建要在不同线程中调用的函数时(并且使用bind)通常,通常是稍后/以异步方式调用的函数),您将面临对象不再有效的巨大危险.
绑定看起来整洁,但这些错误是最难找到的,因为错误被捕获(即在调用函数时)与错误发生的位置不同(在绑定时)并且可能非常难以工作确切地说当时正在调用哪个函数,因此它被绑定的位置.
在您作为参考传递的变量范围内加入线程时,在您的实例中是安全的.因此,当您知道是这种情况时,有一种传递引用的机制.
它不是我希望看到的语言的一个特征,特别是因为很可能有很多现有的代码依赖于它制作一个副本,如果它只是通过引用自动进行就会破坏(然后需要一个明确的方法来强制复制).
如果要通过引用传递参数,则std::thread
必须将每个参数括在std::ref
:
thread t1(f1, std::ref(ret));
Run Code Online (Sandbox Code Playgroud)
更多信息在这里.