c++ 學習之 多線程(二) thread的參數傳遞

c++ 學習之 多線程(二) thread的參數傳遞

前言

上一篇文章中講了thread的四種構造函數,接下來給大家講一講thread的參數傳遞。

正文

1.初始化構造函數
利用初始化構造函數創建對象,第一個位置必須要傳入一個可調用對象。c++ 中的可調用對象大概有這麼幾種:普通函數 ,類成員函數,類靜態函數,仿函數,函數指針,lambda表達式,std::function。不瞭解可調用對象的可以戳這裏,我寫的另一篇關於可調用對象的文章。
(1)普通函數
用普通函數來初始化thread對象很簡單,只需要把函數名傳進去即可,函數中的參數按照順序傳入:

#include<stdio.h>
#include<thread>
void fun(int a,int b)
{
    printf("%d\n",a+b);
}
int main()
{
    int a =1;
    int b =2;
    std::thread t(fun,a,b);
    t.join();
}

輸出結果爲 : 3

(2)類成員函數
類成員函數是有真正地址的,利用 &類名::函數名 可以拿到成員函數的地址。注意,最好先創建一個了類對象,不建議用臨時對象。第二位參數傳入該對象。

#include<stdio.h>
#include<thread>
class A
{
  public:
  void fun(int a,int b)
  {
     printf("%d\n",a+b);
  }
};
int main()
{
     int a =1;
     int b =2;
     A c;
     std::thread t(&A::fun,c,a,b);
     t.join();
}

輸出結果爲 : 3
(3)類靜態成員函數
類靜態成員函數不需要指定類對象。

#include<stdio.h>
#include<thread>
class A
{
  public:
  static void fun(int a,int b)
  {
     printf("%d\n",a+b);
  }
};
int main()
{
     int a =1;
     int b =2;
     std::thread t(&A::fun,a,b);
     t.join();
}

輸出結果爲: 3

(4) 仿函數(即用類對象創建線程)
仿函數是使用類來模擬函數調用行爲,我們只要重載一個類的operator()方法,即可像調用一個函數一樣調用類。這種方式用得比較少。

#include<stdio.h>
#include<thread>
class A
{
 public:
  void operator()(int a,int b)//實現了對()的重載
  {
     printf("%d\n",a+b);
  }
};
int main()
{
   int a =1;
   int b =2;
   A c;
   std::thread t(c,a,b);
   t.join();
}

輸出結果爲 : 3
我們只需要在類的內部對() 進行重載,然後就可以將該類的對象作爲可調用對象初始化thread。

(5)函數指針
沒啥說的,函數指針的使用,和回調函數用法差不多。

#include<stdio.h>
#include<thread>
void fun(int a, int b)
{
 printf("%d\n", a + b);
}
int main()
{
	 int a = 1;
	 int b = 2;
	 void (*p)(int, int) = fun;
	 std::thread t(p, a, b);
	 t.join();
}

輸出結果爲 : 3
(6)lambda表達式

將匿名函數作爲可調用對象創建thread。

#include<stdio.h>
#include<thread>
int main()
{
 int a = 1;
 int b = 2;
 auto c = [](int a, int b) {printf("%d\n", a + b); };
 std::thread t(c, a, b);
 t.join();
 
}

輸出結果爲 : 3

(7) std::function
std::function 可以用來描述C++中的可調用實體,它可以兼容所有可調用對象,自然也可以通過它來初始化thread對象。

#include<stdio.h>
#include<thread>
#include<functional>
std::function<void(int, int)> Function;

//普通函數
void fun(int a,int b)
{
 printf("普通函數:%d\n", a + b);
}
void fun2(int a, int b)
{
 printf("函數指針:%d\n", a + b);
}

class A
{
public:
 //類成員函數
 void fun1(int a, int b)
 {
  printf("類成員函數:%d\n", a + b);
 }
 //靜態成員函數
 static void fun2(int a, int b)
 {
  printf("靜態成員函數:%d\n", a + b);
 }
 //仿函數
 void operator ()(int a, int b)
 {
  printf("仿函數(類對象):%d\n", a + b);
 }
};
int main()
{
 int a = 1;
 int b = 2;
 
 //lambda表達式
 auto lam = [](int a, int b) {printf("lambda表達式:%d\n", a + b); };
 Function = lam;
 std::thread t1(Function, a, b);
 t1.join();
 
 //函數指針
 void(*p)(int, int) = fun2;
 Function = p;
 t1 = std::thread(Function, a, b);
 t1.join();
 
 //靜態成員函數
 Function = &A::fun2;
 t1 = std::thread(Function, a, b);
 t1.join();
 
 //成員函數
 A c;
 Function = std::bind(&A::fun1,c, std::placeholders::_1, std::placeholders::_2);// 此時將對象c指定爲對象實例
 t1 = std::thread(Function,a,b);// 這裏不用將c傳進去了
 t1.join();
 
 //仿函數
 A d;
 Function = d;
 t1 = std::thread(Function, a, b);
 t1.join();
 }

輸出結果:
lambda表達式:3
函數指針:3
靜態成員函數:3
類成員函數:3
仿函數(類對象):3

可以用到的初始化的方式大概就這樣幾種,都得用到可調用對象。

2.移動構造函數
首先我們要明白移動構造函數的用途,是把一個thread對象的線程轉移到構造出來的thread對象上,可以通俗的理解成一次性賦值,過後被移動的thread對象將不在執行線程。但是我們不也能直接將被移動thread對象作爲參數傳進去,需要用std::move(),將它轉換爲右值

#include<stdio.h>
#include<thread>
void fun()
{
 printf("I love China\n");
}
int main()
{
 std::thread t(fun);
 std::thread t1(std::move(t));
 t1.join();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章