C++ 多线程(3)std::thread 详解

2021-01-02 01:28

阅读:752

标签:src   head   调用   containe   memory   拷贝构造函数   get   线程   就会   

@

目录
  • 一、头文件
  • 二、std::thread 构造函数
  • 三、其他成员函数
  • 四、传递临时参数作为线程对象的注意事项
    • 4.1 解决办法:
    • 4.2 原因分析
    • 4.3 总结
  • 五、传递类对象、智能指针作为线程参数
    • 5.1 修改子线程中的对象,不会影响主线程中的对象
    • 5.2 传递智能指针
  • 参考链接:

一、头文件

std::thread 在 头文件中声明,因此使用 std::thread 时需要包含 头文件。

二、std::thread 构造函数

技术图片

(1). 默认构造函数,创建一个空的 thread 执行对象。
(2). 初始化构造函数,创建一个 thread对象,该 thread对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
(3). 拷贝构造函数(被禁用),意味着 thread 不可被拷贝构造。
(4). move 构造函数,move 构造函数,调用成功之后 x 不代表任何 thread 执行对象。

注意:可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached.

std::thread 各种构造函数例子如下(参考):

#include 
#include 
#include 
#include 
 
void f1(int n)
{
    for (int i = 0; i 

三、其他成员函数

指向当前线程std::this_thread
例如std::this_thread::get_id()

get_id 获取线程 ID。
joinable 检查线程是否可被 join。
join Join 线程。
detach Detach 线程
swap Swap 线程 。
native_handle 返回 native handle。
hardware_concurrency [static] 检测硬件并发特性

四、传递临时参数作为线程对象的注意事项

注意:以下问题主要都是在detach情况下发生,join下不会发生。

			   线程(函数)的传入参数,引用&会失效,指针*还是会传递地址。
#include 
#include 
#include 
using namespace std;

void myprint(const int &i, char *pmybuf){
    //i并不是mavar的引用,实际是值传递
    //推荐改为const int i
    cout

4.1 解决办法:

#include 
#include 
#include 
using namespace std;

void myprint(const int i, const string &pmybuf){
    //i并不是mavar的引用,实际是值传递
    //推荐改为const int i
    cout

4.2 原因分析

#include 
#include 
#include 
using namespace std;

class A{
public:
    int m_i;
    A(int a):m_i(a){cout

4.3 总结

1、线程(函数)的传入参数,引用&会失效,指针*还是会传递地址。因为主线程如果销毁了变量内存,子线程的运行就会出错,因此尽量不要在detach()的线程中用传递主线程中的指针
2、为了防止主线程先结束,detach()的线程还没构造,调用构造的时候要显示的调用类的拷贝构造,即为了防止主线程先结束,只有复制一份内存才行
3、想要传递真正的引用需要使用std::ref(param_nanm)

thread thread_obj(func,std::ref(num))

五、传递类对象、智能指针作为线程参数

5.1 修改子线程中的对象,不会影响主线程中的对象

#include 
#include 
using namespace std;

class A {
public:
    mutable int m_i; //mutable关键字,任何情况下都可以修改变量。即使实在const中也可以被修改
    A(int i) :m_i(i) {}
};

void myPrint(const A& pmybuf)
{
    pmybuf.m_i = 199;

}

int main()
{
    A myObj(10);
    //myPrint(const A& pmybuf)中引用不能去掉,如果去掉会多创建一个对象
    //const也不能去掉,去掉会出错
    //即使是传递的const引用,但在子线程中还是会调用拷贝构造函数构造一个新的对象,
    //所以在子线程中修改m_i的值不会影响到主线程
    //如果希望子线程中修改m_i的值影响到主线程,可以用thread myThread(myPrint, std::def(myObj));
    //这样const就是真的引用了,myPrint定义中的const就可以去掉了,类A定义中的mutable也可以去掉了
    //此时拷贝构造也只执行一次了
    thread myThread(myPrint, myObj);
    myThread.join();
    //myThread.detach();

    cout 

5.2 传递智能指针

#include 
#include 
#include 
using namespace std;

void myPrint(unique_ptr ptn)
{
	cout  up(new int(10));
	//独占式指针只能通过std::move()才可以传递给另一个指针
	//传递后up就指向空,新的ptn指向原来的内存
	//所以这时就不能用detach了,因为如果主线程先执行完,ptn指向的对象就被释放了
	thread myThread(myPrint, std::move(up));
	myThread.join();
	//myThread.detach();

	return 0;
}

参考链接:

https://en.cppreference.com/w/cpp/thread/thread/thread

C++ 多线程(3)std::thread 详解

标签:src   head   调用   containe   memory   拷贝构造函数   get   线程   就会   

原文地址:https://www.cnblogs.com/long5683/p/12995049.html


评论


亲,登录后才可以留言!