考虑以下简短程序:
#include <thread>
int Foo() {
while (1);
}
int main(){
std::thread t(Foo);
std::thread s(Foo);
// (std::thread(Foo));
t.join();
}
使用
编译并运行(永久)g++ -Wl,--no-as-needed DoubleBufferTest.cc -o DoubleBufferTest -std=c++0x -pthread
在注释掉的行中,我试图使用here描述的技术匿名声明一个新线程。但是,当该行被注释回来时,我可以编译但运行时会出现以下错误:
terminate called without an active exception
Aborted (core dumped)
如何正确地匿名声明线程?
注意,我在g++ 4.4.7
。
答案 0 :(得分:12)
std::thread
的析构函数将调用std::terminate
。
很遗憾,您无法创建这样的匿名线程对象 - 您需要引用thread
对象才能调用join()
或detach()
。
Scott Meyers在Going Native 2013上发表演讲,他创建了一个包含线程的RAII类,并在析构函数中调用join。你可以做类似的事情:
class ThreadRAII {
public:
ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
~ThreadRAII() { if (t.joinable()) { t.join(); }
private:
std::thread t;
};
你可以像这样使用它
(ThreadRAII(std::thread(Foo)));
但是,你想以这种方式创建一个线程的唯一原因是你不关心它何时(或如果)结束,所以在这种情况下,join没有多大意义。您应该修改析构函数以分离:
~ThreadRAII() { if (t.joinable()) { t.detach(); }
正如评论中所建议的那样,通过完美转发到构建中的内部线程,您可以更容易地使用它:
class ThreadRAII2 {
public:
template <typename Func, typename ...Args>
explicit ThreadRAII2(Func&& func, Args&&... args) :
t(func, std::forward<Args>(args)...) { }
~ThreadRAII2() {
if (t.joinable()) t.detach();
}
private:
std::thread t;
};
然后你可以像你原来想的那样使用它,不需要分离:
(ThreadRAII2(Foo));
或者,如果Foo
接受参数(例如Foo(int)
):
(ThreadRAII2(Foo, 42));
答案 1 :(得分:11)
你可以这样做:
std::thread(Foo).detach();
答案 2 :(得分:4)
我不认为这是(你所指的技术)可以用线程。
看看这里;
30.3.1.3 thread destructor [thread.thread.destr]
〜螺纹();
如果joinable()则终止(),否则没有效果。 [注意:要么隐式 在析构函数中分离或连接joinable()线程可能会导致 难以调试正确性(用于分离)或性能(用于连接)错误 仅在引发异常时遇到。因此程序员必须确保 在线程仍可连接时,析构函数永远不会被执行。 - 结束说明]
基本上,当执行继续执行违反上述规则的下一行时,您正在创建的临时匿名对象(即线程)将被销毁。