实参的生命周期
给std::thread传递参数的时候要注意,参数是引用或者指针的情况下,要注意生命周期的问题
看代码
#include <iostream>
#include <thread>
#include <chrono>
#include <fstream>
using namespace std::chrono_literals;
void func_str(const std::string & str)
{
std::this_thread::sleep_for(2s);
std::cout << "ThreadArg data is " << str << '\n';
}
void start_thread(void)
{
char buffer[6] = {'a','b','c','d','e','\0'};
std::thread t(func_str, std::string(buffer));
// 可以测试 std::thread t(func_str, buffer); //crash
t.detach();
}
int main(int argc, char** argv)
{
std::thread t1(start_thread);
t1.join();
std::this_thread::sleep_for(3s); // 3s是字面量 since C++14 可以用 std::chrono::seconds(3)替代
return 0;
}
我们考虑变量生命周期的问题,尤其是线程是分离的情况下,给予线程参数的线程有可能提前退出而释放资源,导致持有参数对象的线程访问了已经销毁的资源,尤其是对于局部变量。
上边的代码是为了保证线程 t 对资源的访问是独立的,所以用一个join线程t1来启动线程t, 为了观察到t线程的行为,所以又让主线程main,sleep一段时间,否则程序因为进程的结束,而回收线程资源
参数是引用类型
要使用std::ref
#include <iostream>
#include <thread>
#include <chrono>
#include <fstream>
using namespace std::chrono_literals;
class ThreadArg
{
public:
ThreadArg():data(123456)
{
std::cout<<"constructor"<<std::endl;
}
ThreadArg(const ThreadArg & rhs):data(rhs.data)
{
std::cout<<"copy constructor"<<std::endl;
}
~ThreadArg()
{
std::cout<<"destructor"<<std::endl;
}
void setData(int value)
{
this->data = value;
}
void printData(int num)
{
std::cout << "ThreadArg data is " << data <<" "<<num<<'\n';
}
private:
int data;
};
void func(ThreadArg & arg)
{
arg.setData(1000);
}
int main(int argc, char** argv)
{
ThreadArg arg;
std::thread t1(func,std::ref(arg)); //不加引用可能编译失败
t1.join(); // 需要在thread对象销毁之前决定线程是 join 还是deatch ,否则程序会异常终止
arg.printData(100);
return 0;
}
传递一个类成员函数
int main(int argc, char** argv)
{
ThreadArg arg;
std::thread t(&ThreadArg::printData, &arg,100);
t.join();
return 0;
}
参数是unique_ptr
void func_ptr(std::unique_ptr<ThreadArg> ptr)
{
ptr->setData(1000);
}
int main(int argc, char** argv)
{
std::unique_ptr<ThreadArg> ptr{new ThreadArg};
std::thread t(func_ptr, std::move(ptr));
t.join();
if (ptr)
{
ptr->printData(100);
}
return 0;
}
可以参考https://blog.csdn.net/veghlreywg/article/details/86529678 了解unique_ptr的使用