std::get<C++11多线程库>(07):向线程函数传递参数(3)

 
 1  /*
 2  * 实例场景:
 3  * 2. std::thread 构造函数的第一个参数为成员函数时,参数的传递。
 4  *    传递方式:std::thread第一个参数为成员函数的函数指针, std::thread 从第二个开始的参数,依次传递给成员函数的参数表
 5  *      Obj obj;
 6  *      std::thread t(&Obj::func, &obj, param1);
 7  *      std::thread t(&Obj::func, &obj, param1, param2, ..., paramn);
 8  *
 9  *  * * 分别就参数的几种常见形式进行讨论:
10  *
11  *      Object obj;
12  *      Param param(10);
13  *
14  *        a) 参数为值类型,    例如 Param。     func形参地址与实参地址不同,发生了: 拷贝构造+移动构造。
15  *           std::thread t(&Object::func, &obj, param);
16  *
17  *        b) 参数为引用类型,  例如 Param &。   func形参地址与实参地址分两种方式而不同  !!!请注意:默认变量类型和自定义类类型的情况并不一样!!!
18  *           b-1) 默认方式
19  *           std::thread t(&Object::func, &obj, param);  形参地址与实参地址不同, 发生了:拷贝构造。
20  *
21  *           b-2) std::ref() 方式
22  *           std::thread t(&Object::func, &obj, std::ref(param)); 形参地址与实参地址相同, 未发生拷贝构造,未发生移动构造
23  *
24  *        c) 参数为指针类型,  例如 int *。   func形参地址与实参地址相同,未发生拷贝。
25  *          std::thread t(&Object::func, &obj, &param);
26  */

 * 问-思考:
 * 2. std::thread 构造函数执行时,不同的参数类型在传递时,都发生了什么事情?比如:值类型,引用类型,指针类型
 
 1 //! [2] ====================== *实例场景-2=====+=====问-思考-2 *==================
 2 template<typename T>
 3 class luckyBear{
 4 public:
 5     luckyBear(T t):m_t(t){
 6         std::cout<<"luckyBear<"<<_typeName()<<"> 构造函数执行..."<<std::endl;
 7     }
 8     luckyBear(luckyBear & other):m_t(other.m_t){
 9         std::cout<<"luckyBear<"<<_typeName()<<"> 拷贝构造函数执行..."<<std::endl;
10     }
11     luckyBear(luckyBear &&other){
12         m_t = std::move(other.m_t);
13         std::cout<<"luckyBear<"<<_typeName()<<"> 移动构造函数执行..."<<std::endl;
14     }
15     ~luckyBear(){
16         std::cout<<"luckyBear<"<<_typeName()<<"> 析构函数执行..."<<std::endl;
17     }
18 
19     void operator=(luckyBear &other){
20         m_t = other.m_t;
21         std::cout<<"luckyBear<"<<_typeName()<<"> 赋值运算符函数执行..."<<std::endl;
22     }
23 
24     void operator=(luckyBear &&other){
25         m_t = std::move(other.m_t);
26         std::cout<<"luckyBear<"<<_typeName()<<"> 移动赋值运算符函数执行..."<<std::endl;
27     }
28 
29     T value(){
30         return m_t;
31     }
32 
33 private:
34     std::string _typeName(){
35        const std::type_info & _type = typeid(T);
36        return _type.name();
37     }
38 
39 private:
40     T m_t;
41 };
42 
43 
44 template<typename T>
45 class thread_test : public luckyBear<T>{
46 
47 public:
48     thread_test():luckyBear<T>(0){}
49 };
50 
51 typedef luckyBear<int> VType;          //Value type
52 typedef luckyBear<int>& RType; //Reference type
53 typedef luckyBear<int>* PType; //Pointer type
54 
55 class thread_construct{
56 
57 public:
58     void func1(VType v){
59         std::cout<<v.value()<<std::endl;
60     }
61 
62     void func2(RType rv){
63         std::cout<<rv.value()<<std::endl;
64     }
65 
66     void func3(PType pv){
67         std::cout<<pv->value()<<std::endl;
68     }
69 };
 1 //! [2-1] 值类型传递: (1次)拷贝构造 + (1次)移动构造
 2 
 3 //分析
 4 /*
 5   1-从局部变量到线程的独立空间中,发生了拷贝构造;
 6   2-从线程的独立空间到线程入口函数,发生了移动构造;
 7   3-形参和实参地址不同;
 8 */
 9 int main(int argc, char *argv[]){
10 
11     VType vt(10);
12 
13     thread_construct _c;
14     std::thread _t1(&thread_construct::func1, &_c, vt);
15 
16     _t1.join();
17     std::cout<<"...lucky bear..."<<std::endl;
18     return 0;
19 
20 }
21 //打印输出:
22 /*
23     luckyBear<int> 构造函数执行...
24     luckyBear<int> 拷贝构造函数执行...
25     luckyBear<int> 移动构造函数执行...
26     10
27     luckyBear<int> 析构函数执行...
28     luckyBear<int> 析构函数执行...
29     ...lucky bear...
30     luckyBear<int> 析构函数执行...
31 */
32 //! [2-1]
 1 //! [2-2-1] 引用类型传递--默认方式: (1次)拷贝构造
 2 
 3 //分析
 4 /*
 5     1. 从局部变量到线程的独立空间中,发生了拷贝构造, “默认参数要拷贝到线程独立内存中,即使参数是引用的形式”;
 6     2. 从线程的独立空间到线程入口函数,属于常规的给引用参数传值, 引用即别名,不开辟新空间;
 7     3. 形参和实参地址不同;
 8 */
 9 int main(int argc, char *argv[]){
10 
11     VType vt(10);
12 
13     thread_construct _c;
14     std::thread _t1(&thread_construct::func2, &_c, vt);   //默认方式
15 
16     _t1.join();
17     std::cout<<"...lucky bear..."<<std::endl;
18     return 0;
19 }
20 //打印输出:
21 /*
22 luckyBear<int> 构造函数执行...
23 luckyBear<int> 拷贝构造函数执行...
24 10
25 luckyBear<int> 析构函数执行...
26 ...lucky bear...
27 luckyBear<int> 析构函数执行...
28 */
29 //! [2-2-1]
 1 //! [2-2-2] 引用类型传递--std::ref()方式:   不发生拷贝构造,不发生移动构造
 2 
 3 //分析
 4 /*
 5     1. 从局部变量到线程的独立空间中,属于常规的给引用参数传值, 引用即别名,不开辟新空间;
 6     2. 从线程的独立空间到线程入口函数,属于常规的给引用参数传值, 引用即别名,不开辟新空间;
 7     3. 形参和实参地址相同;
 8     4. std::ref() 方式传递引用类型参数,可以做到线程内对参数的修改会作用到线程外部的实参变量,反过来也是一样。
 9 */
10 int main(int argc, char *argv[]){
11 
12     VType vt(10);
13 
14     thread_construct _c;
15     std::thread _t1(&thread_construct::func2, &_c, std::ref(vt));  //std::ref() 方式
16 
17     _t1.join();
18     std::cout<<"...lucky bear..."<<std::endl;
19     return 0;
20 }
21 //打印输出:
22 /*
23 luckyBear<int> 构造函数执行...
24 10
25 ...lucky bear...
26 luckyBear<int> 析构函数执行...
27 */
28 //! [2-2-2]
 1 //! [2-3-1] 指针类型传递--默认方式:   不发生拷贝构造,不发生移动构造
 2 
 3 //分析
 4 /*
 5     1. 从局部变量到线程的独立空间中,属于常规的给指针参数传值, 多个指针指向同一地址空间,不开辟新空间;
 6     2. 从线程的独立空间到线程入口函数,属于常规的给指针参数传值, 多个指针指向同一地址空间,不开辟新空间;
 7     3. 形参和实参地址相同;
 8     4. 默认方式方式传递指针类型参数,可以做到线程内对参数的修改会作用到线程外部的实参变量,反过来也是一样。
 9 */
10 int main(int argc, char *argv[]){
11 
12     VType vt(10);
13 
14     thread_construct _c;
15     std::thread _t1(&thread_construct::func3, &_c, &vt);  //默认方式
16 
17     _t1.join();
18     std::cout<<"...lucky bear..."<<std::endl;
19     return 0;
20 }
21 //打印输出:
22 /*
23 luckyBear<int> 构造函数执行...
24 10
25 ...lucky bear...
26 luckyBear<int> 析构函数执行...
27 */
28 //! [2-3-1]
 1 //! [2-3-2] 指针类型传递--std::ref()方式:   不可以这样使用,编译报错
 2 
 3 //分析
 4 /*
 5 */
 6 int main(int argc, char *argv[]){
 7 
 8     VType vt(10);
 9 
10     thread_construct _c;
11 
12     //error info: C2893:未能使函数模板(unkown-type std::invoke(_Callable &&, _Types &&...)专用化
13     //std::thread _t1(&thread_construct::func3, &_c,std::ref(vt));  //std::ref() 方式
14 
15     //_t1.join();
16     std::cout<<"...lucky bear..."<<std::endl;
17     return 0;
18 }
19 //打印输出:
20 /*
21 */
22 //! [2-3-2]
23 //! [2]

std::get<C++11多线程库>(07):向线程函数传递参数(4)

原创文章, 转载请注明出处!

原文地址:https://www.cnblogs.com/azbane/p/15335042.html