std :: promise左值引用与右值引用之间的区别

时间:2018-05-15 11:44:03

标签: multithreading c++11 promise future

我的理解是,如果我们调用从promise获得的未来,那么它将等到调用set_value,如果永远不会被调用,程序将永远等待但是当我使用promise rvalue reference时,这种行为不起作用(它是抛出破碎的承诺未来错误)虽然同样使用左值参考(永远等待)。任何推理都是因为我相信它应该在rvalue引用的情况下永远等待吗?

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

}

2 个答案:

答案 0 :(得分:2)

使用此形式的thread构造函数时:

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

在线程完成执行之前,临时(或第二种情况下的p参数)被销毁,这会触发std::future_error,因为共享状态尚未就绪(set_value已有没被调用过。)

但是,如果您使用std::reference_wrapper

std::thread t(calculateValue, std::ref(p));

然后,原始的promise不会被移动,它仍然存在,并且在main结束之前不会调用它的析构函数。从未达到过,因为主线程将等待fut.get()

底线:问题根本与calculateValue参数的形式无关。它是关于你是否从p转移到临时的,它实际上定义了与未来(及其共享状态)相关的承诺的析构函数是否被破坏。

答案 1 :(得分:1)

当您执行std::move(p)时,您有效地放弃了p对该主题的所有权。 p函数中的承诺main没有任何未来,所以说。

当您传递引用(使用std::ref)时,您仍然拥有承诺,并且线程函数只引用main函数中的承诺。它类似于将指针传递给变量p

这就是你的程序在移动承诺时无法等待的原因,但在传递引用时会等待它。