提问人:abergmeier 提问时间:5/20/2012 最后编辑:Barryabergmeier 更新时间:7/13/2020 访问量:474142
使用成员函数启动线程
Start thread with member function
问:
我正在尝试构造一个带有成员函数的函数,该函数不接受参数并返回。我无法找出任何有效的语法 - 编译器无论如何都会抱怨。正确的实现方法是什么,以便它返回一个执行?std::thread
void
spawn()
std::thread
test()
#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 是 T 类型的对象或对 类型 T 或对派生自 T 的类型的对象的引用;
- ((*t1).*f)(t2, ..., tN) 当 f 是指向类 T 的成员函数的指针且 t1 不是前面描述的类型之一时 项目;
- 当 N == 1 且 f 是指向类 T 的成员数据的指针且 t 1 是类型为 T 的对象或对类型为 T 的对象的引用或对派生自 T
的类型的对象的
引用时;- (*t1).*f 当 N == 1 且 f 是指向类 T 的成员数据的指针且 t 1 不是上一项所述的类型之一时;
- f(t1, t2, ..., tN) 在所有其他情况下。
我想指出的另一个一般事实是,默认情况下,线程构造函数将复制传递给它的所有参数。这样做的原因是参数可能需要比调用线程更长,复制参数可以保证这一点。相反,如果要真正传递引用,可以使用 created by .std::reference_wrapper
std::ref
std::thread (foo, std::ref(arg1));
通过这样做,您承诺您将负责保证当线程对参数进行操作时参数仍然存在。
请注意,上面提到的所有内容也可以应用于 和 。std::async
std::bind
评论
std::thread
std::bind
std::bind
bind
由于您使用的是 C++11,因此 lambda-expression 是一个不错的干净解决方案。
class blub {
void test() {}
public:
std::thread spawn() {
return std::thread( [this] { this->test(); } );
}
};
由于可以省略,因此可以缩短为:this->
std::thread( [this] { test(); } )
或者只是(已弃用)
std::thread( [=] { test(); } )
评论
std::move
[=]
[&]
[=]
[&]
std::thread spawn() { int i = 10; return std::thread( [&] { std::cout<<i<<"\n"; } ); }
)
这是一个完整的例子
#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)
评论
delete
一些用户已经给出了他们的答案,并很好地解释了这一点。
我想再补充一些与线程有关的东西。
如何使用函子和线程。 请参考以下示例。
线程将在传递对象时创建自己的对象副本。
#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 //i.e. 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();
}
评论
thread t((CB()));
CB
@hop5 和 @RnMss 建议使用 C++11 lambda,但如果您处理指针,则可以直接使用它们:
#include <thread>
#include <iostream>
class CFoo {
public:
int m_i = 0;
void bar() {
++m_i;
}
};
int main() {
CFoo foo;
std::thread t1(&CFoo::bar, &foo);
t1.join();
std::thread t2(&CFoo::bar, &foo);
t2.join();
std::cout << foo.m_i << std::endl;
return 0;
}
输出
2
从这个答案中重写的样本将是:
#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(&Wrapper::member1, this);
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread(&Wrapper::member2, this, arg1, arg2);
}
};
int main() {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
tw1.join();
std::thread tw2 = w->member2Thread("hello", 100);
tw2.join();
return 0;
}
评论
std::move( std::thread(func) );
std::thread
std::move