Multithreading std::promise左值引用与右值引用之间的差异
我的理解是,如果我们调用从promise获得的未来,那么它将一直等到set_值被调用,如果从未调用,那么程序将永远等待,但不知何故,当我使用promise rvalue引用时,这种行为不起作用(它抛出了破坏的promise future错误),尽管它在左值引用中起作用(永远等待)。有什么理由,因为我认为在右值引用的情况下它也应该永远等待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
#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
函数中的promisep
没有任何未来
当您传递一个引用(使用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构造函数时它是如何放弃所有权的