如何匿名声明std :: thread?

mer*_*011 10 c++ multithreading c++11 stdthread

考虑以下简短程序:

#include <thread>

int Foo() {
while (1);
}

int main(){
    std::thread t(Foo);
    std::thread s(Foo);

    // (std::thread(Foo));

    t.join();
}
Run Code Online (Sandbox Code Playgroud)

这编译和运行(永远),与

g++ -Wl,--no-as-needed DoubleBufferTest.cc -o DoubleBufferTest -std=c++0x -pthread
Run Code Online (Sandbox Code Playgroud)

在注释掉的行中,我试图使用此处描述的技术匿名声明一个新线程.但是,当该行被注释回来时,我可以编译但运行时会出现以下错误:

terminate called without an active exception            
Aborted (core dumped)                                   
Run Code Online (Sandbox Code Playgroud)

我怎样才能正确地匿名声明一个帖子?

请注意,我在g++ 4.4.7.

zmb*_*zmb 12

std::threadstd::terminate如果线程尚未连接或分离,则析构函数将调用.

所以很遗憾你不能像这样创建一个匿名的线程对象 - 你需要引用该thread对象才能调用join()或者detach().

Scott Meyers在2013年的Going Native上发表了一篇演讲,他创建了一个包含线程的RAII类,并在析构函数中调用join.你可以做类似的事情:

class ThreadRAII {
public:
  ThreadRAII(std::thread&& thread): t(std::move(thread)) {}
  ~ThreadRAII() { if (t.joinable()) { t.join(); }

private:
  std::thread t;
};
Run Code Online (Sandbox Code Playgroud)

见他的博客文章谈话的更多信息.

你可以像这样使用它

(ThreadRAII(std::thread(Foo)));
Run Code Online (Sandbox Code Playgroud)

但是,您希望以这种方式创建线程的唯一原因是,如果您不关心它何时(或如果)结束,那么在这种情况下,连接没有多大意义.您应该修改析构函数以分离:

~ThreadRAII() { if (t.joinable()) { t.detach(); }
Run Code Online (Sandbox Code Playgroud)

正如评论中所建议的那样,通过完美转发到构造中的内部线程,您可以更容易地使用它:

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;
};
Run Code Online (Sandbox Code Playgroud)

然后你可以像你原来想的那样使用它,不需要分离:

(ThreadRAII2(Foo));
Run Code Online (Sandbox Code Playgroud)

或者,如果Foo接受参数(例如Foo(int)):

(ThreadRAII2(Foo, 42));
Run Code Online (Sandbox Code Playgroud)


How*_*ant 11

你可以这样做:

std::thread(Foo).detach();
Run Code Online (Sandbox Code Playgroud)