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

发布于 2024-10-19 11:20:04 字数 557 浏览 6 评论 0原文

这是示例:

#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 标志。

这是预期的行为吗?

该程序是否没有数据竞争?

谢谢

This is the example:

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

And the output is:

ret=0
ret=5

Compiled with gcc 4.5.2, with and without -O2 flag.

Is this expected behavior?

Is this program data race free?

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

能怎样 2024-10-26 11:20:04

std::thread 的构造函数推导参数类型并按值存储它们的副本。这是为了确保参数对象的生命周期至少与线程的生命周期相同。

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

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

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

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

The constructor of std::thread deduces argument types and stores copies of them by value. This is needed to ensure the lifetime of the argument object is at least the same as that of the thread.

C++ template function argument type deduction mechanism deduces type T from an argument of type T&. All arguments to std::thread are copied and then passed to the thread function so that f1() and f2() always use that copy.

If you insist on using a reference, wrap the argument using boost::ref() or std::ref():

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

Or, if you prefer simplicity, pass a pointer. This is what boost::ref() or std::ref() do for you behind the scene.

想你的星星会说话 2024-10-26 11:20:04

如果您想通过引用 std::thread 传递参数,则必须将每个参数括在 std::ref 中:

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

更多信息 此处

If you want to pass parameters by reference to a std::thread you must enclose each of them in std::ref:

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

More info here.

老街孤人 2024-10-26 11:20:04

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

对于非常量引用,通常存在传递局部变量的危险,对于常量引用,它可能是临时的,并且当您创建要在不同线程中调用的函数时(并且使用绑定)一般来说,通常是稍后/以异步方式调用的函数),您将面临对象不再有效的巨大危险。

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

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

这不是我希望看到改变的语言功能,特别是因为可能有很多现有代码依赖于它来制作副本,如果它只是自动引用引用,那么副本就会中断(然后需要一种显式的方法来强制复制)。

That you are required an explicit std::ref() (or boost::ref()) in these situations is actually a very useful safety feature as passing a reference can be by nature a dangerous thing to do.

With a non-const reference there is quite often a danger that you are passing in a local variable, with a const-reference it might be a temporary, and as you are creating a function to be called in a different thread (and with bind in general, often a function to be called later / in an asynchronous way) you will have the big danger of the object being no longer valid.

binding looks tidy but these bugs are the hardest to find, as where the error is caught (i.e. in calling the function) is not the same place that the error was made (at the time of binding) and it can be very hard to work out exactly which function is being called at the time, and therefore where it was bound.

It is safe in your instance as you join the thread in the scope of the variable you are passing as reference. Therefore when you know that to be the case there is a mechanism for passing a reference.

It is not a feature of the language I would like to see changed, particularly as there is probably a lot of existing code relying on it making a copy that would break if it just took by reference automatically (and would then need an explicit way to force a copy).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文