C++ 使用成员函数启动线程

C++ 使用成员函数启动线程,c++,multithreading,c++11,C++,Multithreading,C++11,我正在尝试构造一个std::thread,其中包含一个成员函数,该函数不接受任何参数并返回void。我想不出任何有效的语法——不管发生什么,编译器都会抱怨。实现spawn()以返回执行test()的std::thread的正确方法是什么 #包括 B类{ 无效测试(){ } 公众: std::thread spawn(){ 返回{test}; } }; 更新:我想解释更多的观点,其中一些观点也在评论中讨论过 上述语法是根据调用定义(§20.8.2.1)定义的: 定义调用(f,t1,t2,…,t

我正在尝试构造一个
std::thread
,其中包含一个成员函数,该函数不接受任何参数并返回
void
。我想不出任何有效的语法——不管发生什么,编译器都会抱怨。实现
spawn()
以返回执行
test()
std::thread
的正确方法是什么

#包括
B类{
无效测试(){
}
公众:
std::thread spawn(){
返回{test};
}
};

更新:我想解释更多的观点,其中一些观点也在评论中讨论过

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

定义调用(f,t1,t2,…,tN),如下所示:

  • (t1.*f)(t2,…,tN)当f是指向类T的成员函数的指针,t1是类型T的对象或对类型T的对象的引用时 类型T或对从T派生的类型的对象的引用
  • ((*t1)。*f)(t2,…,tN)当f是指向类T的成员函数的指针且t1不是前面描述的类型之一时 项目
  • t1.*f,当N==1且f是指向类T的成员数据的指针且t1是类型T或a的对象时
    对T型对象的引用或对a型对象的引用
    由T派生的类型
  • (*t1)。*f,当N==1且f是指向类T的成员数据的指针且t1不是上一项中描述的类型之一时
  • f(t1,t2,…,tN)在所有其他情况下

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

std::thread (foo, std::ref(arg1));
通过这样做,您可以保证在线程对参数进行操作时,这些参数仍然存在


请注意,上面提到的所有内容也可以应用于
std::async
std::bind


更新:我想解释更多的观点,其中一些观点也在评论中讨论过

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

定义调用(f,t1,t2,…,tN),如下所示:

  • (t1.*f)(t2,…,tN)当f是指向类T的成员函数的指针,t1是类型T的对象或对类型T的对象的引用时 类型T或对从T派生的类型的对象的引用
  • ((*t1)。*f)(t2,…,tN)当f是指向类T的成员函数的指针且t1不是前面描述的类型之一时 项目
  • t1.*f,当N==1且f是指向类T的成员数据的指针且t1是类型T或a的对象时
    对T型对象的引用或对a型对象的引用
    由T派生的类型
  • (*t1)。*f,当N==1且f是指向类T的成员数据的指针且t1不是上一项中描述的类型之一时
  • f(t1,t2,…,tN)在所有其他情况下

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

std::thread (foo, std::ref(arg1));
通过这样做,您可以保证在线程对参数进行操作时,这些参数仍然存在



请注意,上面提到的所有内容也可以应用于
std::async
std::bind

,因为您使用的是C++11,lambda表达式是一个很好且干净的解决方案

class blub {
    void test() {}
  public:
    std::thread spawn() {
      return std::thread( [this] { this->test(); } );
    }
};
由于
此->
可以省略,因此可以缩短为:

std::thread( [this] { test(); } )
或者只是(不推荐)


std::thread([=]{test();})

因为您使用的是C++11,所以lambda表达式是一个很好且干净的解决方案

class blub {
    void test() {}
  public:
    std::thread spawn() {
      return std::thread( [this] { this->test(); } );
    }
};
由于
此->
可以省略,因此可以缩短为:

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

这是一个完整的例子

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

一些用户已经给出了答案,并且解释得很好

我想再添加一些与线程相关的内容。

  • 如何使用函子和线程。 请参考下面的例子

  • 线程将在传递对象时创建自己的对象副本

    #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()
    {
        CB obj;
        //thread t(obj);
        thread t(std::ref(obj));
        t.join();
    }
    

    一些用户已经给出了答案,并且解释得很好

    我想再添加一些与线程相关的内容。

  • 如何使用函子和线程。 请参考下面的例子

  • 线程将在传递对象时创建自己的对象副本

    #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()
    {
        CB obj;
        //thread t(obj);
        thread t(std::ref(obj));
        t.join();
    }
    

    @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;
    }
    
    改写后的样本将是:

    #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;
    }
    
    #包括
    #包括
    类包装器{
    公众:
    无效成员1(){
    
    std::cout@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;
    }
    
    改写后的样本将是:

    #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;
    }
    
    #包括
    #包括
    类包装器{
    公众:
    无效成员1(){
    
    std::难道你的意思是函数返回void,称为void,或者它只是没有任何参数。你能为你正在尝试做的事情添加代码吗?你测试过吗?(我知道)