用成员函数启动线程

我想构build一个std::thread的成员函数,不接受任何参数,并返回void 。 我无法弄清楚任何可行的语法 – 无论如何编译器都会抱怨。 什么是正确的方式来实现spawn()以便它返回一个执行test()std::thread

 #include <thread> class blub { void test() { } public: std::thread spawn() { return { test }; } }; 
 #include <thread> #include <iostream> class bar { public: void foo() { std::cout << "hello from member function" << std::endl; } }; int main() { std::thread t(&bar::foo, bar()); t.join(); } 

编辑:核算你的编辑,你必须这样做:

  std::thread spawn() { return std::thread(&blub::test, this); } 

更新:我想解释一些点,其中一些也已经在评论中讨论。

上述语法是根据INVOKE定义(§20.8.2.1)定义的:

定义INVOKE(f,t1,t2,…,tN)如下:

  • (t1,…,f)(t2,…,tN),当f是类T的成员函数的指针时,t1是types为T的对象或对types为T的对象的引用,从T派生的types的对象;
  • 当f是指向类T的成员函数的指针并且t1不是在前一项中描述的types时,((* t1)。* f)(t2,…,tN)
  • t1。* f当N == 1时,f是一个指向类T的成员数据的指针,t 1是typesT或a的对象
    引用Ttypes的对象或对象的引用
    从T派生的types;
  • (* t1)。* f当N == 1且f是指向类T的成员数据的指针时,t 1不是前一项中描述的types之一;
  • f(t1,t2,…,tN)。

我想指出的另一个一般事实是,默认情况下,线程构造函数将复制传递给它的所有参数。 这样做的原因是参数可能需要比调用线程长,复制参数保证。 相反,如果你真的想传递一个引用,你可以使用由std::ref创build的std::reference_wrapper

 std::thread (foo, std::ref(arg1)); 

通过这样做,你有希望保证在线程运行时参数仍然存在。


请注意,上面提到的所有东西也可以应用于std::asyncstd::bind

既然你正在使用C ++ 11,lambdaexpression式是一个不错的和干净的解决scheme。

 class blub { void test() {} public: std::thread spawn() { return std::thread( [this] { this->test(); } ); } }; 

因为this->可以省略,所以可以缩短为:

 std::thread( [this] { test(); } ) 

要不就

 std::thread( [=] { test(); } ) 

这是一个完整的例子

 #include <thread> #include <iostream> class Wrapper { public: void member1() { std::cout << "i am member1" << std::endl; } void member2(const char *arg1, unsigned arg2) { std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl; } std::thread member1Thread() { return std::thread([=] { member1(); }); } std::thread member2Thread(const char *arg1, unsigned arg2) { return std::thread([=] { member2(arg1, arg2); }); } }; int main(int argc, char **argv) { Wrapper *w = new Wrapper(); std::thread tw1 = w->member1Thread(); std::thread tw2 = w->member2Thread("hello", 100); tw1.join(); tw2.join(); return 0; } 

用g ++编译产生如下结果

 g++ -Wall -std=c++11 hello.cc -o hello -pthread i am member1 i am member2 and my first arg is (hello) and second arg is (100) 

一些用户已经给出了他们的答案,并很好地解释了它。

我想添加几个有关线程的东西。

  1. 如何使用函子和线程。 请参考下面的例子。

  2. 线程将在传递对象时创build对象的副本。

     #include<thread> #include<Windows.h> #include<iostream> using namespace std; class CB { public: CB() { cout << "this=" << this << endl; } void operator()(); }; void CB::operator()() { cout << "this=" << this << endl; for (int i = 0; i < 5; i++) { cout << "CB()=" << i << endl; Sleep(1000); } } void main() { CB obj; // please note the address of obj. thread t(obj); // here obj will be passed by value //ie thread will make it own local copy of it. // we can confirm it by matching the address of //object printed in the constructor // and address of the obj printed in the function t.join(); } 

达到同样目的的另一种方式是:

 void main() { thread t((CB())); t.join(); } 

但是如果你想通过引用传递对象,那么使用下面的语法:

 void main() { CB obj; //thread t(obj); thread t(std::ref(obj)); t.join(); }