我理解std::thread
符号here,并转载如下
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
void f1(int n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread " << n << " executing\n";
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
void f2(int& n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 2 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
int main()
{
int n = 0;
std::thread t1; // t1 is not a thread
std::thread t2(f1, n + 1); // pass by value
std::thread t3(f2, std::ref(n)); // pass by reference
std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread
t2.join();
t4.join();
std::cout << "Final value of n is " << n << '\n';
}
因为f1
和f2
的定义在main
范围内但未能理解
#ifndef THREADED_H_
#define THREADED_H_
class Threadme
{
long count;
public:
Threadme();
void run(void);
void delay(long);
};
#endif
#include "threaded.h"
#include <iostream>
#include <chrono>
Threadme::Threadme() : count(0) {}
void Threadme::delay(long seconds)
{
std::chrono::steady_clock::time_point end_t = std::chrono::system_clock::now() + std::chrono::seconds(seconds);
while(std::chrono::system_clock::now() < end_t)
;
}
void Threadme::run(void)
{
while(count < 10)
{
++count;
std::cout << count << std::endl;
delay(1);
}
}
#include <cstdlib>
#include <thread>
#include "threaded.h"
int main(int argc, char *argv[]){
std::thread t1(&Threadme::run, Threadme());
t1.join();
return EXIT_SUCCESS;
}
特别是表达式std::thread t1(&Threadme::run, Threadme());
,因为它与定义run
之外的线程函数main
有关。为什么引用&
以及为什么线程parameters
是构造函数调用?
答案 0 :(得分:3)
&Foo::mem
其中Foo
是类类型而mem
是Foo
的成员(函数或值),是用于获取指向成员的指针的C ++表示法(函数)或价值)。存在一种用于在对象上调用成员函数指针的特殊语法,但这通常通过使用std::mem_fun
来消除,这会将成员函数指针转换为普通函数,其中第一个参数必须是成员函数的类型取自。
std::thread
理解这里发生的事情并完全做到这一点:对作为第二个参数传递的对象调用Foo::mem
。
在本地重现此内容而不实际涉及std::thread
的小例子:
#include <functional>
class Foo { void mem() {} };
int main() {
Foo f;
f.mem(); // normal invoke
auto func = std::mem_fun(&Foo::mem);
func(std::ref(f)); // invoke mem on f
func(f); // invoke mem on a copy of f
func(&f); // invoke mem on f through a pointer
}
为什么在构建mem_fun
时我们不需要std::thread
?它
通过过载自动检测这些情况
这是正确的事情。
答案 1 :(得分:-1)
您可以将ThreadMe
的成员函数视为接受类型为ThreadMe*
的隐式第一个参数的函数 - 也称为this
。这个类比不是100%正确,可能会被一些语言律师粉碎,但它有助于理解你在那里的电话。
std::thread
和许多其他接受函数和参数的类/函数,例如: std::bind
和std::function
接受指向成员函数的指针,后跟一个必须在其上调用函数的对象,否则放入该隐含的第一个参数。
所以void ThreadMe::run()
可以被视为void run(ThreadMe&);
那么困扰你的电话很容易理解。考虑你的第二个例子:
void f1(int n);
int n;
std::thread t2(f, n); //calls f in a new thread, passing n
现在只在需要时创建int:
std::thread t2(f, int()); //calls f, passing a copy of the int that has been created here...
对于可能没有多大意义的整数,但是它有一个对象:
void run(ThreadMe&);
std::thread t1(run, ThreadMe()); //conceptually the same as above
既然我们知道这个隐含的第一个参数的成员函数只比语法糖多一点,那么你所拥有的调用仍然只是上面的内容:
void ThreadMe::run(); //implicit first argument is a ThreadMe&
std::thread t1(ThreadMe::run, ThreadMe()); //pass a copy of that newly created ThreadMe as the implicit first argument of the run method.
如果你知道lambdas,这非常相似,即它将一个新的ThreadMe
的副本传递给调用该副本上运行的线程::
ThreadMe threadMe;
std::thread t1([=](){ threadMe.run(); });
事实上,由于参数绑定到std::thread
构造函数引擎下发生的函数有点不寻常,我更喜欢使用lambdas,因为它们明确解释了线程必须做的任何事情。在这种情况下,我不会创建临时ThreadMe
来调用线程,我会在线程内部创建一个非临时的:
std::thread t1([](){
ThreadMe threadMe;
threadMe.run();
});