使用 std::future
的右值引用作为参数是否合法?由于 std::future::get()
未标记为 const
,是否存在潜在问题需要注意?
如果我有遗漏,请告诉我。
这是完整的代码片段:
#include <future>
#include <vector>
#include <iostream>
//int factorial(std::future<int> fut) //works, because there is a move constructor
int factorial(std::future<int>&& fut)
{
int res = 1;
int num = fut.get();
for(int i=num; i>1; i--)
{
res *= i;
}
return res;
}
int main()
{
std::promise<int> prs;
std::future<int> fut_num{prs.get_future()};
std::vector<std::future<int>> vec;
vec.push_back(std::async(std::launch::async, factorial, std::move(fut_num)));
prs.set_value(5);
for(auto& fut: vec)
{
std::cout << fut.get() << std::endl;
}
}
我知道如果传递左值引用,事情会变得容易得多。但是我仍然关注函数何时使用std :: future
的右值引用作为参数。
更新:
通常,右值引用绑定到临时对象。而且非const方法可以由被右引用指向的对象调用吗?我担心这是不合法的,因为非const方法可能会修改临时对象。
std::async
(或者说std::thread
)的任何参数都会被完美转发到一些局部变量中,这些变量属于新线程。因此对于factorial(int&& ref)
,该参数指向此局部存储而不是main::fut_num
变量,即使您像int x=5; std::async(factorial, x)
这样调用它。因此,如果x
超出范围,异步调用也不受影响。请参见例如 https://dev59.com/_lsX5IYBdhLWcg3wPdQ7#34078246 - Quimbyx
超出作用域,async
调用也不受影响”是因为x
是按值传递的。如果它被传递为std::ref(x)
,“如果x
超出作用域,async
调用将出错。我对吗? 2,这个代码片段是合法的(注释指示修改)。我对吗? - Johnx
被完美转发到x_temp
,并且使用x_temp
调用了阶乘函数,而不是x
。因此,如果factorial
接受一个引用,那么它将是对安全的x_temp
的引用,该引用始终会在线程之外存在,而x
可能会超出其作用域。是的,确切地说,std::ref
是危险的,因为阶乘函数将接收到对x
的引用。std::ref
,那么你可能会遇到未定义行为,很可能会导致段错误。