C++线程的移动语义

news2024/11/5 4:37:03

在C++标准库中,std::thread 和 std::ifstream 都设计为不可复制的(non-copyable),但可移动的(movable)。这样做的原因和它们的实现方式以及移动操作的优点和使用场合如下:

原因

  1. 不可复制的理由:
    • std::thread:一个线程对象表示一个实际的操作系统线程,复制一个线程对象意味着复制一个正在运行的线程,这在逻辑上是不可行的,因为一个线程不能同时在两个地方运行。
    • std::ifstream:一个文件流对象通常与一个特定的文件描述符相关联,复制文件流对象会导致多个对象共享同一个文件描述符,这会导致不一致的文件状态和未定义的行为。
  2. 可移动的理由:
    • 允许资源的转移:通过移动操作,可以将线程或文件流对象所控制的资源从一个对象转移到另一个对象,而不会出现共享资源的情况。这保证了资源的唯一性和一致性。

实现

std::thread 和 std::ifstream 的不可复制和可移动特性是通过以下方式实现的:

不可复制:

通过将复制构造函数和复制赋值操作符声明为 delete 或 private,防止对象的复制。

class thread {
public:
    thread(const thread&) = delete;
    thread& operator=(const thread&) = delete;
};

可移动:

通过定义移动构造函数和移动赋值操作符,允许对象的资源在对象之间转移。

class thread {
public:
    thread(thread&& other) noexcept {
     // 转移资源
    }

    thread& operator=(thread&& other) noexcept {
        if (this != &other) {
            // 释放当前资源,转移其他对象的资源
        }

        return *this;
    }
};

优点和使用场合

  1. 线程资源的唯一性:
    • 通过移动操作,可以确保线程资源在任何时刻只被一个对象控制,避免了资源共享带来的潜在问题。
    • 示例:在一个函数内部创建一个线程,并将其移动到函数外部的一个对象中:
      std::thread create_thread() {
          std::thread t([]() {
              // 线程函数
          });
      
          return t; // 移动构造函数被调用
      }
      
      std::thread outer_thread = create_thread(); // 移动赋值操作符被调用

  2. 灵活性和性能:
    • 移动操作允许对象在函数调用、返回值等场景中更灵活地传递,而不需要进行资源复制,这在性能敏感的场景中尤为重要。
    • 示例:在多线程编程中,传递线程对象时不需要复制线程的内部状态,减少了开销。
  3. 处理所有权转移:
    • 在某些设计模式中,移动操作可以用于明确地转移资源的所有权,确保资源的完整性。
    • 示例:在工厂模式中,生成的线程对象可以通过移动操作转移给其他组件进行管理。

总结

std::thread 和 std::ifstream 支持移动而不支持复制的理由是为了保证资源的唯一性和减少潜在的资源共享问题。通过移动构造函数和移动赋值操作符,这些对象可以在不复制底层资源的情况下进行转移,这提高了系统的灵活性、性能和安全性。在多线程编程和文件处理等场景中,这种设计模式尤为重要,确保了资源的安全管理和高效使用。

线程移动后,原线程所拥有的资源也一并转移了,原线程“只剩空壳”,析构了

当你移动一个 std::thread 对象时,它的底层线程资源会被转移给新的对象,而原来的 std::thread 对象将不再拥有任何资源,变成一个“空壳”。在C++中,这种情况下原线程对象的析构是安全的,不会导致任何问题。

线程移动的实现细节

1. 移动构造函数

class thread {
public:
    thread(thread&& other) noexcept {
        // 转移资源
        native_handle_ = other.native_handle_;
        other.native_handle_ = nullptr; // 原对象的资源指针置空
    }
        // 其他成员函数和数据成员

private:
    std::thread::native_handle_type native_handle_;
};

在这个例子中,native_handle_ 是一个表示底层线程资源的指针。通过移动构造函数,原线程对象的 native_handle_ 被赋值给新对象,而原对象的 native_handle_ 被置为 nullptr,表示它不再控制任何线程资源。

2. 移动赋值操作符

thread& operator=(thread&& other) noexcept {
    if (this != &other) {
        // 释放当前资源

        if (joinable()) {
            join(); // 或者 detach(),取决于设计
        }
        
        // 转移其他对象的资源
        native_handle_ = other.native_handle_;
        other.native_handle_ = nullptr;
    }

    return *this;
}

在移动赋值操作符中,首先确保当前对象不是自身,然后释放当前对象可能持有的资源(如果已经有一个线程在运行),最后将原对象的资源指针转移给当前对象,并将原对象的资源指针赋空。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2232325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

02-Dubbo特性及工作原理

02-Dubbo特性及工作原理 Dubbo 的特性 这里说一下 Dubbo 最主要的特性,从这些特性中,就可以看出来我们为什么要选用 Dubbo,也可以将 Dubbo 和 Spring Cloud 进行对比,比如我们搭建一套微服务系统,出于什么考虑选用 Dub…

通义灵码AI程序员你在用吗?

大家好,我是袁庭新。之前给大家介绍过AI编码助手——通义灵码,这期给大家分享通义灵码AI程序员的一些功能。 随着大模型的持续进化,在语义理解、代码生成、开发工作流等方面的能力也获得了持续、全面的提升。你说,要是有个编程小…

好难的题啊

序: 1.极坐标本质为变化的圆:动曲线---》格林公式 2.曲线积分常见的化简就是对dx,dy进行操作,这要求寻找到合适函数,而极坐标就是天然的函数(参数方程) 3.重积分--》累次积分--》单独看其中一…

大学适合学C语言还是Python?

在大学学习编程时,选择C语言还是Python,这主要取决于你的学习目标、专业需求以及个人兴趣。以下是对两种语言的详细比较,帮助你做出更明智的选择: C语言 优点: 底层编程:C语言是一种底层编程语言&#x…

开源模型应用落地-Qwen2.5-7B-Instruct与TGI实现推理加速

一、前言 目前,大语言模型已升级至Qwen2.5版本。无论是语言模型还是多模态模型,均在大规模多语言和多模态数据上进行预训练,并通过高质量数据进行后期微调以贴近人类偏好。在本篇学习中,将集成 Hugging Face的TGI框架实现模型推理…

【QT】Qt对话框

个人主页~ Qt窗口属性~ Qt窗口 五、对话框2、Qt内置对话框(1)Message Box(2)QColorDialog(3)QFileDialog(4)QFontDialog(5)QInputDialog 五、对话框 2、Qt内…

ubuntu交叉编译expat库给arm平台使用

1.下载expat库源码: https://github.com/libexpat/libexpat/release?page=2 wget https://github.com/libexpat/libexpat/release/download/R_2_3_0/expat-2.3.0.tar.bz2 下载成功: 2.解压expat库,并进入解压后的目录: tar xjf expat-2.3.0.tar.bz2 cd expat-2.3.0 <…

NPOI 操作详解(操作Excel)

目录 1. 安装 NPOI 2. 使用 NPOI 创建新 Excel 文件 3. 设置列宽和行高 1. 设置列宽 2. 设置行高 3. 同时设置列宽和行高 4. 设置统一的行高 5. 设置统一的列宽 6. 应用统一的行高和列宽 4. 合并单元格 5. 设置单元格样式&#xff08;字体、边框、背景色等&#xf…

【Javaee】网络原理-http协议(二)

前言 上一篇博客初步介绍了抓包工具的安装及使用&#xff0c;介绍了http请求报文与响应报文的格式。​​​​​​【Javaee】网络原理—http协议&#xff08;一&#xff09;-CSDN博客 本篇将详细介绍http的方法和http报文中请求头内部键值对的含义与作用&#xff0c;以及常见状…

大模型系列——AlphaZero/强化学习/MCTS

AlphaGo Zero无需任何人类历史棋谱&#xff0c;仅使用深度强化学习&#xff0c;从零开始训练三天的成就已远远超过了人类数千年积累的围棋知识。 1、围棋知识 &#xff08;1&#xff09;如何简单理解围棋知识 &#xff08;2&#xff09;数子法分胜负&#xff1a;https://zhu…

得物多模态大模型在重复商品识别上的应用和架构演进

重复商品治理介绍 根据得物的平台特性&#xff0c;同一个商品在平台上不能出现多个链接&#xff0c;原因是平台需要保证一品一链的特点&#xff0c;以保障商品的集中竞价&#xff0c;所以说一个商品在整个得物平台上只能有一个商详链接&#xff0c;因此我们需要对一品多链的情…

1、DevEco Studio 鸿蒙仓颉应用创建

1. 仓颉鸿蒙应用简介 因为仓颉是静态编译型语言&#xff0c;使用仓颉开发的应用执行效率更高。而且主打全场景&#xff0c;后续可并入仓颉生态&#xff0c;其和ArkTS都是基于ArkUI进行开发&#xff0c;最大的区别是typescript和仓颉语法间的差异。 2. 应用创建 前置条件&…

vue3项目中实现el-table分批渲染表格

开篇 因最近工作中遇到了无分页情景下页面因大数据量卡顿的问题&#xff0c;在分别考虑并尝试了懒加载、虚拟滚动、分批渲染等各个方法后&#xff0c;最后决定使用分批渲染来解决该问题。 代码实现 表格代码 <el-table :data"currTableData"borderstyle"wi…

LeetCode:82. 删除排序链表中的重复元素 II(重复的一个都不保留)

目录 题目描述: 代码: 第一种: 第二种: 题目描述: 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,4,5] 输出&#xff1a;[1,2…

偏差与方差的基本概念

在机器学习中&#xff0c;Bias-Variance Tradeoff&#xff08;偏差-方差权衡&#xff09; 是一个核心概念&#xff0c;帮助我们理解模型的误差来源以及如何调节模型复杂度以达到更好的泛化性能。在这篇博客中&#xff0c;我们将深入讨论什么是偏差和方差&#xff0c;以及如何平…

0-ARM Linux驱动开发-字符设备

一、字符设备概述 Linux 系统中&#xff0c;设备被分为字符设备、块设备和网络设备等。字符设备以字节流的方式进行数据传输&#xff0c;数据的访问是按顺序的&#xff0c;一个字节一个字节地进行读取和写入操作&#xff0c;没有缓冲区。例如&#xff0c;终端&#xff08;/dev…

HTML 基础标签——表格标签<table>

文章目录 1. `<table>` 标签:定义表格2. `<tr>` 标签:定义表格行3. `<th>` 标签:定义表头单元格4. `<td>` 标签:定义表格单元格5. `<caption>` 标签:为表格添加标题6. `<thead>` 标签:定义表格头部7. `<tbody>` 标签:定义表格…

【优选算法】——二分查找!

目录 1、二分查找 2、在排序数组中查找元素的第一个和最后一个位置 3、搜索插入位置 4、x的平方根 5、山脉数组的封顶索引 6、寻找峰值 7、寻找旋转排序数组中的最小值 8、点名 9、完结散花 1、二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组…

东北虎豹国家公园shp格式范围

东北虎豹国家公园地处中国吉林、黑龙江两省交界的老爷岭南部&#xff08;珲春—汪清—东宁—绥阳&#xff09;区域&#xff0c;东起吉林省珲春林业局青龙台林场&#xff0c;与俄罗斯滨海边疆区接壤&#xff0c;西至吉林省大兴沟林业局岭东林场&#xff0c;南自吉林省珲春林业局…

Spring 中的 Environment 对象

可参考官网&#xff1a;Environment Abstraction 核心概念 Environment 对象对两个关键方面进行建模&#xff1a;profiles 和 属性&#xff08;properties&#xff09;。 Profile 简单来说&#xff1a;profile 机制在 IOC 容器中提供了一种机制&#xff1a;允许在不同的环境…