Multithreading std::promise左值引用与右值引用之间的差异

Multithreading std::promise左值引用与右值引用之间的差异,multithreading,c++11,promise,future,Multithreading,C++11,Promise,Future,我的理解是,如果我们调用从promise获得的未来,那么它将一直等到set_值被调用,如果从未调用,那么程序将永远等待,但不知何故,当我使用promise rvalue引用时,这种行为不起作用(它抛出了破坏的promise future错误),尽管它在左值引用中起作用(永远等待)。有什么理由,因为我认为在右值引用的情况下它也应该永远等待 #include <iostream> #include <future> #include <thread> #inclu

我的理解是,如果我们调用从promise获得的未来,那么它将一直等到set_值被调用,如果从未调用,那么程序将永远等待,但不知何故,当我使用promise rvalue引用时,这种行为不起作用(它抛出了破坏的promise future错误),尽管它在左值引用中起作用(永远等待)。有什么理由,因为我认为在右值引用的情况下它也应该永远等待

#include <iostream>
#include <future>
#include <thread>
#include <chrono>
void calculateValue(std::promise<int> &&p)
//void calculateValue(std::promise<int> &p) //uncomment this it will wait
{
  using namespace std::chrono_literals;

  std::cout<<"This is start of thread function "<<std::endl;
  //Do long operations
  std::this_thread::sleep_for(2s);
 // p.set_value(8);
  std::cout<<"This is end of thread function "<<std::endl;

}
int main() {

  std::promise<int> p;
  auto  fut = p.get_future();
  std::thread t(calculateValue,std::move(p));
  //uncomment this it will wait
  //std::thread t(calculateValue,std::ref(p);
  std::cout<<"main function ..."<<std::endl;
  std::cout<<"value is "<<fut.get()<<std::endl;
  t.join();
  return 0;

}
#包括
#包括
#包括
#包括
无效计算值(标准::承诺和p)
//void calculateValue(std::promise&p)//取消对此的注释,它将等待
{
使用名称空间std::chrono_文本;

std::cout当您执行
std::move(p)
时,您实际上将
p
的所有权放弃给了线程。可以说,
main
函数中的承诺
p
没有任何未来

当您传递一个引用(使用
std::ref
)时,您仍然拥有承诺,线程函数只在
main
函数中引用承诺。这类似于传递一个指向变量
p
的指针


这就是为什么您的程序在移动承诺时不能等待,但在传递引用时确实会等待。

当您执行
std::move(p)
您有效地将
p
的所有权放弃给线程。可以说,
main
函数中的promise
p
没有任何未来

当您传递一个引用(使用
std::ref
)时,您仍然拥有承诺,线程函数只在
main
函数中引用承诺。这类似于传递一个指向变量
p
的指针


这就是为什么您的程序在移动承诺时无法等待,但在传递引用时确实会等待。

当您使用这种形式的
线程的构造函数时:

std::thread t(calculateValue, std::move(p));
然后,在内部,
p
从移动到
std::promise
的临时对象中。此临时对象用作其参数类型的
calculateValue
的参数:

void calculateValue(std::promise<int> &&p) // option #1
void calculateValue(std::promise<int> p)   // option #2
然后,原始承诺不会从中移动,它仍然存在,并且直到
main
结束时才调用它的析构函数。这永远不会到达,因为主线程将等待
fut.get()



一句话:问题根本与
calculateValue
参数的形式无关。问题在于是否从
p
移动到临时,临时定义了承诺的析构函数是否连接到未来(及其共享状态)是否已销毁。

当您使用这种形式的
线程的构造函数时:

std::thread t(calculateValue, std::move(p));
然后,在内部,
p
从移动到
std::promise
的临时对象中。此临时对象用作其参数类型的
calculateValue
的参数:

void calculateValue(std::promise<int> &&p) // option #1
void calculateValue(std::promise<int> p)   // option #2
然后,原始承诺不会从中移动,它仍然存在,并且直到
main
结束时才调用它的析构函数。这永远不会到达,因为主线程将等待
fut.get()


一句话:问题根本与
calculateValue
参数的形式无关。问题在于你是否从
p
移动到一个临时值,临时值有效地定义了与未来(及其共享状态)相关的承诺的析构函数是否被销毁。

std::move(p)刚刚执行了静态_转换并将其转换为右值,右值由右值引用捕获,因此无法理解在没有调用move构造函数时它是如何放弃所有权的d::move(p)只是做了一个静态_转换,并将其转换为右值,右值由右值引用捕获,因此无法理解在没有调用move构造函数时它是如何放弃所有权的