我试图构造一个std::线程的成员函数,不接受参数并返回void。我想不出任何可行的语法——无论如何编译器都会抱怨。实现spawn()以返回执行test()的std::线程的正确方法是什么?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};
我试图构造一个std::线程的成员函数,不接受参数并返回void。我想不出任何可行的语法——无论如何编译器都会抱怨。实现spawn()以返回执行test()的std::线程的正确方法是什么?
#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)定义的:
Define INVOKE (f, t1, t2, ..., tN) as follows: (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T; ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item; t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T; (*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item; f(t1, t2, ..., tN) in all other cases.
我想指出的另一个普遍事实是,默认情况下线程构造函数将复制传递给它的所有参数。这样做的原因是实参可能需要比调用线程活得更久,复制实参可以保证这一点。相反,如果你真的想传递一个引用,你可以使用std::ref创建的std::reference_wrapper。
std::thread (foo, std::ref(arg1));
通过这样做,您承诺在线程对参数进行操作时,您将注意保证参数仍然存在。
请注意,上面提到的所有内容也可以应用于std::async和std::bind。
其他回答
@hop5和@RnMss建议使用c++ 11的lambdas,但如果你处理指针,你可以直接使用它们:
#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;
}
这是一个完整的例子
#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)
一些用户已经给出了他们的答案,并且解释得很好。
我想补充一些与线程相关的东西。
How to work with functor and thread. Please refer to below example. The thread will make its own copy of the object while passing the object. #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();
}
#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)定义的:
Define INVOKE (f, t1, t2, ..., tN) as follows: (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T; ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of the types described in the previous item; t1.*f when N == 1 and f is a pointer to member data of a class T and t 1 is an object of type T or a reference to an object of type T or a reference to an object of a type derived from T; (*t1).*f when N == 1 and f is a pointer to member data of a class T and t 1 is not one of the types described in the previous item; f(t1, t2, ..., tN) in all other cases.
我想指出的另一个普遍事实是,默认情况下线程构造函数将复制传递给它的所有参数。这样做的原因是实参可能需要比调用线程活得更久,复制实参可以保证这一点。相反,如果你真的想传递一个引用,你可以使用std::ref创建的std::reference_wrapper。
std::thread (foo, std::ref(arg1));
通过这样做,您承诺在线程对参数进行操作时,您将注意保证参数仍然存在。
请注意,上面提到的所有内容也可以应用于std::async和std::bind。
因为你使用的是c++ 11, lambda-expression是一个很好的解决方案。
class blub {
void test() {}
public:
std::thread spawn() {
return std::thread( [this] { this->test(); } );
}
};
因为这个->可以省略,所以可以缩短为:
std::thread( [this] { test(); } )
或者只是(弃用)
Std::thread([=] {test();})