用成员函数启动线程
我想构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::async
和std::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)
一些用户已经给出了他们的答案,并很好地解释了它。
我想添加几个有关线程的东西。
-
如何使用函子和线程。 请参考下面的例子。
-
线程将在传递对象时创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(); }