C++ 我可以返回std::thread吗
从函数返回std::thread安全吗 乙二醇C++ 我可以返回std::thread吗,c++,multithreading,C++,Multithreading,从函数返回std::thread安全吗 乙二醇 std::thread getWindowThread(std::函数f){ 标准:螺纹t(f); 返回t; } std::function func=[](){}; std::thread winT=getWindowThread(func); winT.join(); 是的,很安全。该线程将被移动到winT 是的,只要函数的返回值用于初始化或分配给另一个std::thread对象,它是安全的 std::thread的析构函数的唯一先决条件是jo
std::thread getWindowThread(std::函数f){
标准:螺纹t(f);
返回t;
}
std::function func=[](){};
std::thread winT=getWindowThread(func);
winT.join();
是的,很安全。该线程将被移动到winT 是的,只要函数的返回值用于初始化或分配给另一个std::thread
对象,它是安全的
std::thread
的析构函数的唯一先决条件是joinable()
为false
:
~thread()代码>
效果:如果joinable()
,则调用terminate()
。否则,就没有效果
若要成为可接合()
,线程的ID必须不等于初始化ID的值:
bool joinable()const noexcept代码>
返回:get\uid()
!=<代码>id()
和std::thread
的move构造函数和move赋值运算符指定从线程移动的线程的ID将等于初始ID的值,因此将不可joinable()
:
thread(thread&&x)无异常代码>
后置条件:x.get-id()==id()
和get-id()
返回开始构造之前的x.get-id()
值
thread&operator=(thread&x)无异常代码>
…
后置条件:x.get-id()==id()
和get-id()
返回赋值前的x.get-id()
值。
由于getWindowThread
返回函数局部变量,其返回值将根据返回的对象进行移动构造,而winT
将根据getWindowThread
返回的值进行移动构造,因此您的示例是安全的。返回的线程
对象不再是可连接的
,可以销毁
但是,如果返回的值不用于初始化或分配给另一个std::thread
对象,则其析构函数将调用std::terminate()
,并使程序崩溃。因此,我建议在函数中添加[[nodiscard]]
属性,以确保编译器在这种危险情况下至少发出警告(如果您可以访问C++17功能,否则会有编译器特定的扩展来启用相同的行为):
[[nodiscard]]std::thread getWindowThread(std::function f){
标准:螺纹t(f);
返回t;
}
看一看。您可以检查std::thread
copy构造函数(和复制分配)是否已被删除。在C++中,请参阅更多关于<代码>移动构造函数< /> > >
当您从函数返回std::thread时,它返回的对象是move-constructed,并且变量winT
也将是move-constructed,因为函数返回具有值类别的对象
这应该有效,不会导致任何未定义的行为。您可能会认为,一旦从函数返回std::thread
,它将被销毁,它的资源必须释放,并且它的线程可能会被销毁
但如前所述,在函数中创建的对象将被移动构造为构造winT
对象
详细信息:
林克说:
如果*this有一个关联的线程(joinable()==true),则调用std::terminate()
因此,要安全地销毁任何std::thread对象,您需要确保它不可连接。提供了有关这方面的更多信息:
因此,默认构造的线程是不可连接的。已完成代码执行但尚未联接的线程仍被视为活动执行线程,因此可以联接
所以,当winT的move构造函数构造它时,它本身就带有从函数返回的对象。在此之后,函数的临时部分将被销毁,因为它不可连接,所以销毁它是安全的。是的,代码定义了行为,并按照您的预期工作。你有什么怀疑的理由吗?我有一个关于gmock返回线程的后续问题,例如:std::function lamda=[](){};std::线程和线程(lamda);EXPECT_调用(,getWindowThread()).willrepeated(返回(wThread));由于无法复制线程,因此引发异常。我怎样才能归还模拟文件?@vedikaseth谷歌的文档涵盖了这一点。如果你仍然不知道该做什么,你应该把它作为一个新问题来问。
std::thread getWindowThread(std::function<void()> f){
std::thread t(f);
return t;
}
std::function<void()> func = [](){};
std::thread winT = getWindowThread(func);
winT.join();
[[nodiscard]] std::thread getWindowThread(std::function<void()> f) {
std::thread t(f);
return t;
}
std::thread winT = getWindowThread(func);