繁体   English   中英

指针和引用之间的区别(作为线程参数)

[英]Difference between pointer and reference as thread parameter

这是示例:

#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;   
}

输出为:

ret=0
ret=5

使用gcc 4.5.2编译,带有和不带有-O2标志。

这是预期的行为吗?

该程序数据竞赛免费吗?

谢谢

std::thread的构造函数推导参数类型并按值存储它们的副本。 这需要确保自变量对象的生存期至少与线程的生存期相同。

C ++模板函数参数类型推导机制从类型T&的参数推导类型T 复制std::thread所有参数,然后将其传递给线程函数,以便f1()f2()始终使用该副本。

如果您坚持使用引用,请使用boost::ref()std::ref()包装参数:

thread t1(f1, boost::ref(ret));

或者,如果您更喜欢简单性,请传递一个指针。 这就是boost::ref()std::ref()在幕后为您做的事情。

在这种情况下,您需要显式的std::ref() (或boost::ref() )实际上是非常有用的安全功能,因为传递引用本质上是一件危险的事情。

使用非const引用时,通常存在传递本地变量的危险,使用const引用时,它可能是临时的,并且在创建要在其他线程中调用的函数时(以及使用bind时)通常,通常是一个以后要用异步方式调用的函数),您将面临对象不再有效的巨大危险。

绑定看起来很整洁,但是这些错误是最难发现的,因为捕获错误的位置(即调用函数)与发生错误的位置不同(绑定时),并且很难处理确切地指出当时正在调用哪个函数,以及它的绑定位置。

在将线程作为引用传递的变量范围内加入线程时,在您的实例中是安全的。 因此,当您知道这种情况时,就有一种传递引用的机制。

这不是我希望看到的语言功能的变化,特别是因为可能有很多现有代码依赖它来制作副本,如果仅自动引用它就会破坏副本(然后需要一种明确的方式来实现)强制复制)。

如果要通过引用传递给std::thread参数,则必须将每个参数都包含在std::ref

thread t1(f1, std::ref(ret));

更多信息在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM