0

我理解这里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';
}

因为f1and的定义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());runmain. 为什么引用&以及为什么线程parameters是构造函数调用?

4

2 回答 2

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_funwhen 构造std::thread?它会通过过载自动检测这些情况并自行执行正确的操作。

于 2013-04-30T13:01:01.220 回答
-1

您可以将 的成员函数ThreadMe视为接受类型的隐式第一个参数的函数ThreadMe*- 也称为this. 这个类比不是 100% 正确的,可能会被一些语言律师撕成碎片,但它有助于理解你在那里的电话。

std::threadstd::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在该副本上调用 run 的线程::

ThreadMe threadMe;
std::thread t1([=](){ threadMe.run(); });

事实上,由于在std::thread's 构造函数的底层将参数绑定到函数有点不寻常,我更喜欢使用 lambda,因为它们明确地解释了线程必须做的任何事情。在这种情况下,我不会创建那个临时ThreadMe的来调用线程,我会在线程本身内部创建一个非临时的:

std::thread t1([](){ 
  ThreadMe threadMe;
  threadMe.run(); 
});
于 2013-04-30T13:11:32.653 回答