提问者:小点点

使用成员函数启动线程


我正在尝试构造一个std::thread,该成员函数不接受参数并返回void。 我想不出有什么语法能起作用--编译器无论如何都会抱怨。 实现spawn()以使其返回执行test()std::thread的正确方法是什么?

#include <thread>
class blub {
  void test() {
  }
public:
  std::thread spawn() {
    return { test };
  }
};

共3个答案

匿名用户

#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);
  }

更新:我想再解释一些观点,其中一些观点在评论中也已经讨论过了。

上述语法根据调用定义(§20.8.2.1)定义:

定义INVOKE(f,t1,t2,。。。,tN)如下:

  • (t1.*f)(t2,。。。,tN),当f是指向类T的成员函数的指针,而t1是T类型的对象或对T类型的对象的引用或对从T派生的类型的对象的引用时;
  • (t1.*f)(t2,。。。,tN)
  • ((*t1).*f)(t2,。。。,tN),当f是指向类T的成员函数的指针且t1不是上一项中描述的类型之一时;
  • t1.*f当N==1且f是指向类T的成员数据的指针且t1是T类型的对象或对T类型的对象的
    引用或对从T派生的
    类型的对象的引用时;
  • (*t1).*f,当N==1且f是指向类T的成员数据的指针且t1不是上一项中描述的类型之一时;
  • f(t1,t2,。。。,tN)。

我想指出的另一个普遍事实是,默认情况下,线程构造函数将复制传递给它的所有参数。 这样做的原因是参数可能需要比调用线程的寿命长,复制参数可以保证这一点。 相反,如果要真正传递引用,可以使用由std::ref创建的std::reference_wrapper

std::thread (foo, std::ref(arg1));

这样做,您就保证了当线程对参数进行操作时,您将确保参数仍然存在。

注意,上面提到的所有东西也可以应用于std::asyncstd::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();})

匿名用户

下面是一个完整的示例

#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)