detach()的坑 ,注意点,传递类对象、智能指针、成员函数作为线程函数 (第四讲)

void myprint(const int i,const string &pmybuf)
{
    cout<<i<<endl;//分析发现i并不是mvar的引用,而是值传递。但是并不推荐这么使用
    cout<<pmybuf.c_str()<<endl;//指针在detach子线程时,绝对会有问题。
    return ;
}
int main()
{
    //传递临时对象作为线程参数
    int mvar =1;
    int &myvar=mvar;
    char buf[]="this a test!";
    第一个参数是函数名,从后面开始就是传入这个线程函数的参数
    thread my_th(myprint,mvar,buf);
    buf是在什么时候转换成string的?
    事实上存在,buf的内存被回收了,系统才用buf去转成string。
    //my_th.join();
    my_th.detach();//主线程退出,mvar在子线程中会不会出问题?
    cout<<"I LOve CHNIA"<<endl;
    return 0;
}
将上面的代码换成这个就不会有问题
thread my_th(myprint,mvar,string(buf));//生成一个临时string对象它会绑定到
这里将buf转换成string对象,这是一个可以保证在线程中安全的方法。

thread my_th(myprint,mvar,A(a));


class A{
    public:
    int m_i;
    A(int a):m_i(a){cout<<"构造函数。。。"<<std::this_thread::get_id()<<endl;}
    A(const A &a):a.m_i{cout<<"拷贝构造函数。。。"<<std::this_thread::get_id()<<endl;}
    ~A()cout<<"析构函数。。。"<<std::this_thread::get_id()<<endl;}
};

int main()
{
    int a=1;
    int vara=12;
    thread my_th(myprint,mvar,A(vara));
    
    
    cout<<"I LOve CHNIA"<<endl;
    return 0;
    
}

总结:
1、如果传递int这种简单的参数类型,建议使用值传递,不要使用引用。/2、如果传递类对象,避免隐式类型转换,全部都在创建线程这一行就构建临时对象,然后在函数参数里使用引用来接,否则系统还会多构造一次对象。
建议不使用detach(),只是有jion()。

线程id的概念:
id是一个数字:每个线程,都对应一个线程id,都不同。
c++函数库里面的函数来获取 std::this_thread::get_id()来获取。

使用类对象创建线程

class A{
public:
    mutable int m_i;
	A(int a):m_i(a){cout<<"构造函数"<<std::this_thread::get_id()<<endl;}
	A(const A &a):m_i(a.m_i){cout<<"拷贝构造函数"<<endl;}
	~A(){cout<<"析构函数"<<std::this_thread::get_id()<<endl;}
    void print(const A &buf)
    {
        buf.m_i =199;//修改值不会影响main函数
		cout<<"子线程的参数地址:"<<&buf<<"threadID:"<<std::this_thread::get_id()<<endl;

    }
//std::ref向线程中传递类对象,编译器都会安装
};

int main()
{
   A myobj(10);
   std::thread myth(print,myobj);//将类对象作为线程的参数,会调用到对象拷贝构造函数
   向线程中传递类对象,编译器都会按照拷贝的方式传入
   如果想传递进去的是引用,而不是拷贝,则需要使用std::ref
   //std::thread myth(print,std::ref(myobj));这样传递的就是真的引用,真的会改变这个值,不能使用detach()
   myth(print,&myobj);这样传递的就是真的引用,真的会改变这个值,不能使用detach()
   myth.join();
   
   return 0;
}

-----------------------------


    void print(unique_ptr<int> x)
    {
        
		cout<<"子线程的参数地址:"<<&buf<<"threadID:"<<std::this_thread::get_id()<<endl;

    }
	
    int main()
    {
        unique_ptr<int> p_int(new int(100));//独占方式指针
        std::thread myth(print,std::move(p_int));//修改占方式指针使用std::move()
        myth.join();//在这种情况下,千万不能detach(),不然线程不安全。
        return 0;
    }

----------------------------------------------------------
class A{
public:
    
	A(int a):m_i(a){cout<<"构造函数"<<std::this_thread::get_id()<<endl;}
	A(const A &a):m_i(a.m_i){cout<<"拷贝构造函数"<<endl;}
	~A(){cout<<"析构函数"<<std::this_thread::get_id()<<endl;}
    void thread_work(int num)
   {
	   cout<<"子线程执行了:"<<this<<"threadID = "<<std::this_thread::get_id()<<endl;
	
   }
   
   int m_i;

};

int main()
{
   A myobj(10);//生成一个类对象
   std::thread myth(&A::thread_work,myobj,15);
   //这边的myobj放入子线程会调用拷贝构造函数
   myth.join();
   
   return 0;
}


----------------------------------------------------------
class A{
public:
    
	A(int a):m_i(a){cout<<"构造函数"<<std::this_thread::get_id()<<endl;}
	A(const A &a):m_i(a.m_i){cout<<"拷贝构造函数"<<endl;}
	~A(){cout<<"析构函数"<<std::this_thread::get_id()<<endl;}
    void operator(int num)
   {
	   cout<<"子线程()执行了:"<<this<<"threadID = "<<std::this_thread::get_id()<<endl;
	
   }
   
   int m_i;

};

int main()
{
   A myobj(10);//生成一个类对象
   std::thread myth(myobj,15);//这边的myobj放入子线程会调用拷贝构造函数,复制出一个对象。
   
   
   myth.join();
   
   return 0;
}
发布了101 篇原创文章 · 获赞 73 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/usstmiracle/article/details/103674303