[英]std::thread notation when defining the threaded function
I understand the std::thread
notation presented here and reproduced as follows 我理解这里提供的
std::thread
符号并重现如下
#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';
}
because the definition of f1
and f2
is within main
but fail to understand 因为
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;
}
specifically the expression std::thread t1(&Threadme::run, Threadme());
特别是表达式
std::thread t1(&Threadme::run, Threadme());
as it relates to defining the threaded function run
outside of main
. 因为它涉及定义在
main
之外run
的线程函数。 Why the reference &
and why the thread parameters
is a constructor invocation? 为什么引用
&
以及为什么线程parameters
是构造函数调用?
&Foo::mem
where Foo
is a class type and mem
a member (function or value) of Foo
, is C++ notation for obtaining a pointer to a member (function or value). &Foo::mem
其中Foo
是一个类类型和mem
中的一员(函数或值) Foo
,是用于获得一个指针指向一个构件(函数或值)C ++符号。 There exist a special syntax for invoking a member function pointer on an object, but this is usually sugared away by using std::mem_fun
, which will turn a member function pointer into an ordinary function where the first argument has to be an object of the type the member function was taken from. 存在一种用于在对象上调用成员函数指针的特殊语法,但这通常通过使用
std::mem_fun
来消除,它将成员函数指针转换为普通函数,其中第一个参数必须是对象的对象。类型成员函数取自。
std::thread
understands what is happening here and does exactly that: invoke Foo::mem
on the object passed as the second argument. std::thread
了解这里发生了什么,并且确实这样做:在作为第二个参数传递的对象上调用Foo::mem
。
A small example to reproduce this locally without actually involving std::thread
: 在本地重现此实例而不实际涉及
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
}
Why don't we need the mem_fun
when constructing std::thread
? 为什么在构造
std::thread
时我们不需要mem_fun
? It automatically detects those situations through an overload and does the right thing all by itself. 它通过过载自动检测这些情况,并自行完成正确的事情。
You can see a member function of ThreadMe
as a function that accepts an implicit first parameter of type ThreadMe*
- also known as this
. 您可以将
ThreadMe
的成员函数看作是接受ThreadMe*
类型的隐式第一个参数的ThreadMe*
- 也称为this
。 This analogy is not 100% correct and might be shred to pieces by some language lawyer, but it serves for understanding the call you have there. 这个比喻并非100%正确,可能会被一些语言律师粉碎,但它有助于理解你在那里的电话。
std::thread
and many other classes/functions that accept functions and parameters for them, like eg std::bind
and std::function
accept pointers to member functions, followed by an object on which the function has to be called, or put otherwise, followed by that implicit first parameter. std::thread
和许多其他类/函数接受它们的函数和参数,例如std::bind
和std::function
接受指向成员函数的指针,后跟一个必须在其上调用函数的对象,或放入否则,后跟隐含的第一个参数。
So void ThreadMe::run()
can be seen as void run(ThreadMe&);
所以
void ThreadMe::run()
可以看作是void run(ThreadMe&);
Then the call that bothers you is easy to understand. 然后,困扰你的电话很容易理解。 Consider your second example:
考虑你的第二个例子:
void f1(int n);
int n;
std::thread t2(f, n); //calls f in a new thread, passing n
now create the int just when it's needed: 现在在需要时创建int:
std::thread t2(f, int()); //calls f, passing a copy of the int that has been created here...
with ints that might not make so much sense, but with an object it does: 使用可能没有那么多意义的整数,但它有一个对象:
void run(ThreadMe&);
std::thread t1(run, ThreadMe()); //conceptually the same as above
and since we know thet member functions are just a bit more than syntactic sugar for that implicit first argument, the call you have is still nothing else but the 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.
If you know lambdas, this is very similar, ie it passes a copy of a fresh ThreadMe
to the thread that calls run on that copy:: 如果你知道lambdas,这是非常相似的,即它将一个新的
ThreadMe
的副本传递给调用该副本上运行的线程::
ThreadMe threadMe;
std::thread t1([=](){ threadMe.run(); });
In fact, since the binding of parameters to functions that happens under the hood of std::thread
's constructor is somewhat unusual, I prefer using lambdas, since they explain explicitly anything the thread has to do. 事实上,由于参数绑定到
std::thread
的构造函数引擎下的函数有点不寻常,我更喜欢使用lambdas,因为它们明确解释了线程必须做的任何事情。 In this case I would not create that temporary ThreadMe
to call the thread, I would create a nontemporary inside the thread itself: 在这种情况下,我不会创建临时
ThreadMe
来调用线程,我会在线程内部创建一个非临时的:
std::thread t1([](){
ThreadMe threadMe;
threadMe.run();
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.