精华内容
下载资源
问答
  • 四大特性1.事务的概念事务(Transaction)指的是一操作序列,该操作序列中的多操作要么都做,要么都不做,是一不可分割的工作单位,是数据库环境中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。...

    一.四大特性

    1.事务的概念

    事务(Transaction)指的是一个操作序列,该操作序列中的多个操作要么都做,要么都不做,是一个不可分割的工作单位,是数据库环境中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

    目前常用的存储引擎有InnoDB(MySQL5.5以后默认的存储引擎)和MyISAM(MySQL5.5之前默认的存储引擎),其中InnoDB支持事务处理机制,而MyISAM不支持。

    2. 事务的特性

    事务处理可以确保除非事务性序列内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的序列,可以简化错误恢复并使应用程序更加可靠。

    但并不是所有的操作序列都可以称为事务,这是因为一个操作序列要成为事务,必须满足事务的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这四个特性简称为ACID特性。

    bdf617759d8c345b1a8428202437c083.png

    1.原子性:

    原子是自然界最小的颗粒,具有不可再分的特性。事务中的所有操作可以看做一个原子,事务是应用中不可再分的最小的逻辑执行体。

    使用事务对数据进行修改的操作序列,要么全部执行,要么全不执行。通常,某个事务中的操作都具有共同的目标,并且是相互依赖的。如果数据库系统只执行这些操作中的一部分,则可能会破坏事务的总体目标,而原子性消除了系统只处理部分操作的可能性。

    2.一致性:

    一致性是指事务执行的结果必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库中只包含事务成功提交的结果时,数据库处于一致性状态。一致性是通过原子性来保证的。

    例如:在转账时,只有保证转出和转入的金额一致才能构成事务。也就是说事务发生前和发生后,数据的总额依然匹配。

    3.隔离性:

    隔离性是指各个事务的执行互不干扰,任意一个事务的内部操作对其他并发的事务,都是隔离的。也就是说:并发执行的事务之间既不能看到对方的中间状态,也不能相互影响。

    例如:在转账时,只有当A账户中的转出和B账户中转入操作都执行成功后才能看到A账户中的金额减少以及B账户中的金额增多。并且其他的事务对于转账操作的事务是不能产生任何影响的。

    4.持久性:

    持久性指事务一旦提交,对数据所做的任何改变,都要记录到永久存储器中,通常是保存进物理数据库,即使数据库出现故障,提交的数据也应该能够恢复。但如果是由于外部原因导致的数据库故障,如硬盘被损坏,那么之前提交的数据则有可能会丢失。

    二.事务的隔离级别

    事务的并发问题

    脏读(Dirty read)

    : 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。

    6fd9f32586e3e89e64fc0861d7bf423d.png

    不可重复读(Unrepeatableread):

    指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。

    640bcc9424b6d4c352224ea5dc2f6b3f.png

    幻读(Phantom read):

    幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。

    b3ff375a9177153c58405e457e5651a3.png

    不可重复度和幻读区别:

    不可重复读的重点是修改,幻读的重点在于新增或者删除。

    解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表

    例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。

    例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读

    事务的隔离级别

    事务的隔离级别用于决定如何控制并发用户读写数据的操作。数据库是允许多用户并发访问的,如果多个用户同时开启事务并对同一数据进行读写操作的话,有可能会出现脏读、不可重复读和幻读问题,所以MySQL中提供了四种隔离级别来解决上述问题。

    事务的隔离级别从低到高依次为 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ以及SERIALIZABLE,隔离级别越低,越能支持高并发的数据库操作。

    79bd5ba411880be6a20c83b3b39f1c1b.png

    2.在spring注解开发中,使用isolation 表示事务的隔离级别

    展开全文
  • 你在性格各个方面的偏好清晰度如下图所示: 一、我们与世界相互作用的方式 外向 外向的人更关注自己如何影响外部环境,将心理能量和注意力聚集于外部世界和与他人的交往上。外向的人最喜欢的活动是聚会、讨论、聊天。...

    职业生涯规划设计书

    前言

    人生是条路,漫长而曲折,回首你的人生之路。放眼他的人生之路,你都看见了什么?有人说一路上快乐多多,有人说一路坎坎坷坷。有人说一路上鲜花簇拥。有人说一路上荆棘 ,有人手一路上友爱如香。有人说一路上真情似海。我认为人生路上最多的是选择。人的一生会面临许多次选择,每一次选择都是重要又无奈的。因为选择就意味着放弃。在高二即将结束时,我毅然而然的选择了美术作为我未来的方向,由此我成为了一个美术生,考上了一个美术专业,成为了一个平面设计在读大学生。我想从我选择美术这条道路起,我就对我的职业已经有了初步的规划了。

    想在这里对自我进行一个深层次的了解,对自己未来的职业生涯进行一个更为系统的阐述。

    目录

    前言

    目录

    分析框架

    自我认知

    (一)自我感知

    1、自我概念

    2、个人性格

    3、个人特长

    4、自我感知小结

    (二)职业生涯规划评测

    (三)自我认知小结

    二、职业认知

    (一)外部坏境分析

    1、大学生就业坏境分析

    (二)目标行业分析

    1、平面设计行业现状

    2、平面设计行业前景

    3、平面设计师就业需求

    (三)目标职业分析

    1、平面设计师招聘要求

    2、工业设计师招聘要求

    (四)业余实践

    (五)职业认知小结

    三、职业决策

    (一)确定行业

    (二)确定职业目标

    (1)毕业一年

    (2)毕业五年

    (三)职业决策小结

    四、自我监控

    总结语

    自我认知

    自我认知是一个复杂的过程,全面细致地了解自己是需要多方面思考,借助各种工具来实现的。我将从自我感知和职业生涯规划测评的角度来进行自我认知。

    (一)自我感知

    自我感知主要从自我概念,个人性格和个人志向三方面展开。

    自我概念

    我的偶像是世界著名设计大师——福田繁雄,他是一位多才多艺的全能设计人、变幻莫测的视觉魔术师、推陈出新的方法实践家、热情机智的人道关怀着、幽默灵巧的老顽童。他的设计理念及许多作品都让我深陷其中,感受设计带来的奇妙感觉。我不敢期望能像他那样享誉世界,但我希望自己的作品也能受到别人的认可与喜欢。

    个人性格

    既有外向的一面,又有内向的一面。有时候只要有什么活动,大概都会看到我参加,内向时,可以让人忽略我的存在。对未知事物具有强烈的好奇心。

    个人特长

    有坚持不懈的精神,有虚心问学的勇气,有有错必改的正气,最重要的是我有一颗忠诚的心。

    自我感知小结

    从我的偶像及我自己的性格、特长中我感知到我喜欢未知事物,喜欢设计作品后的感觉,他让我有一种从未有过的成就感。

    (二)职业生涯规划评测

    1、你的性格类型是什么?你做事的动力如何?

    你的动力类型是什么?

    你的长处在哪里?

    什么样的岗位适合你?

    你可以探索的职业有哪些?

    你的短板在哪里?

    你可以尝试的发展建议有哪些?你的性格类型是什么?

    你的性格类型是什么????每个人都希望了解自己性格,相信你也一定很想知道。下面的部分是依据你的测评结果而得到的关于你性格描述。下图是你的测试结果,从中可以得知你的性格类型为: 。你在性格各个方面的偏好清晰度如下图所示:

    一、我们与世界相互作用的方式

    外向

    外向的人更关注自己如何影响外部环境,将心理能量和注意力聚集于外部世界和与他人的交往上。外向的人最喜欢的活动是聚会、讨论、聊天。

    内向的人更关注外部环境的变化对自己的影响,将心理能量和注意力聚集于内部世界,注重内心体验。内向的人喜欢独立思考,看书,避免成为注意的中心,聆听比表达多。

    内向

    二、我们获取信息的主要方式

    感觉

    感觉的人关注由感觉器官获取的具体信息,重视看到的、听到的、闻到的、尝到的、触摸到的事物。他们关注细节、喜欢描述、喜欢使用和琢磨已知的技能。

    直觉的人关注事物的整体和发展趋势,重视灵感、预测和推理。直觉特征的人富于想象和创造,喜欢学习新技能,但容易厌倦,喜欢使用比喻、跳跃性地展现事实。

    直觉

    三、我们的决策方式

    思考

    思考的人重视事物之间的逻辑关系,喜欢通过客观分析做决定。他们理智、客观、公正,认为原则比人情更重要。

    情感的人重视自己和他人的感受。他们富有同情心、善良、和睦、善解人意,考虑行为对他人情感影响,认为人情比原则更重要。

    情感

    四、我们的做事方式

    判断

    判断的人喜欢做计划和决定,愿意进行管理和控制,希望生活井然有序。他们重视结果(重点在于完成任务)、按部就班、有条理、尊重时间期限。

    知觉的人灵活、适应环境、倾向于留有余地,喜欢宽松自由的生活方式。他们重视过程、随信息的变化不断调整目标,喜欢有多种选择。

    知觉

    你的性格类型特点:

    你外表看起来沉默而冷静,但内心非常善良,有同情心,善解人意。你重视与他人建立有深度、真实、共同进步的关系,希望参与有助于自己及他人的进步和内在提升

    展开全文
  • 在最近对云计算的所有关注中,存储更多地被视为基础平台。时至今日,许多云计算提供的仅仅局限于CPU内核的集合,定量的内存分配,低转速存储,或者还有一些面向互联网的IP技术。...存储架构师意识到这些特征...

    在最近对云计算的所有关注中,存储更多地被视为基础平台。时至今日,许多云计算提供的仅仅局限于CPU内核的集合,定量的内存分配,低转速存储,或者还有一些面向互联网的IP技术。近来,出现了有趣的与云计算和存储相关的高级技术,特别是使用Web Services访问方式,使得访问存储不再受限于设备文件或者NFS加载点。

    典型的数据存储和管理的“企业级特征”在IT架构创新上不断推成出新。存储架构师意识到这些特征对于关键业务和生产应用非常重要,但目前的云计算还缺乏这些特征。本篇白皮书的目标是描述企业云计算中存储必备的6个要素。

    一、要素1:性能

    性能需要付出成本。在一个架构良好的应用里,性能和成本处于平衡状态。达到这点的关键是使用合适的技术去匹配企业业务应用的性能,首先要求将企业的业务语言转换成IT模式。因为这种转换困难,通常企业止步于静态的IT架构,无法应对业务变化着的性能需求。企业云计算提供了一个更能应对变化着的性能需求的平台。

    访问模式包括位于OSI模型物理层之上的多层协议的组合(如SOAP, NFS, TCP, IP和FCP)。数据访问包括共享的物理服务层(如以太网)和几个协议层(如SOAP或NFS),一般比专门的物理层(如FC)产生更多的延迟。市场上大多数云计算平台包括Internet的数据访问,产生了更多的数据访问延迟。

    a4623258af193419c60ddf02c33bdd19.png

    对于存储介质,大多数云计算的市场在RAID或JBOD配置中使用SATA磁盘。因为SATA(有段时间被视为近线磁盘)的性能一般比企业磁盘(一般指FC盘)稍差一些,导致存储设备的性能低于应用的需求。

    当你采用低性能存储介质的相对低带宽和高延迟的访问模式时,使用整个存储子系统的企业无法支持更多的关键业务应用的需求。其结果是,这种方案通常仅适用于测试和开发。

    相比来说,企业云计算平台需要提供更多不同性能存储层的选择。当性能需求的变化时,例如,应用从测试迁移到生产环境,存储平台应该能使用这种变化。理想的企业云计算的存储应该有多种性能区,能够被调整,以提供合适的I/O性能级别给业务性能的需求。

    最后,为了满足企业高端存储的性能需求,云计算方案必须采用高于或者目前正在使用的企业级技术。一般使用FC SAN。此外,如何使用技术与技术本身同等重要。在一个系统管理环境里,企业级需求下的虚拟机配置必须能够持续提供高性能

    二、要素2:安全性

    安全性和虚拟化通常被视为相互矛盾的。毕竟虚拟化使得应用从物理硬件和网络边界中解放出来。安全性,换而言之,就是建立边界。企业需要考虑虚拟化设计的初始架构。

    在大多数云计算市场里,无论公有的还是私有的,数据安全性都是基于信任的,这信任通常都在管理程序里。当多数虚机共享物理LUN,CPU和内存时,由管理程序确保数据是否毁坏或者被错误的虚机访问。这与集群服务器多年来面临的基本挑战相同。任何也许需要接管进程的物理服务器必须能访问数据/应用/操作系统的权限。例如,为了主机外备份,LUN也许需要映射给公共的备份服务器。

    在企业云计算中,有两种方式去保护业务数据。第一种涉及系统程序管理安全。主要的目标是:系统尽可能少地被使用,避免任何虚拟机被其他虚拟机造成负面的影响。企业也需要保护LUN被其他服务器访问,如同主机外备份服务器。

    其他需要注意的地方是数据通道。企业必须注意只能给需要维护必要功能的物理服务器提供访问路径。这可以通过NPIV(SAN N端口 ID虚拟化)使用得Zoning、LUN Masking、访问列表、权限配置来完成。

    三、要素3:自动ILM存储

    信息生命周期管理(ILM)曾经成为非常有效的市场行为的重心,被那些出售分层存储的厂商所推崇。虽然ILM本质上非常简单 - 存储的成本与数据的业务价值相匹配,实际的挑战来自于真正的执行效果,众多所谓的ILM方案,粒度都不够细,难以达到这样的目标。

    今天,传统的ILM并没有部署到市场上的大多数云计算平台中。原因有两个,第一,在许多云计算中,大部分磁盘介质采用处于典型ILM方案中的最低层存储,这样就没法把数据往更底层迁移,ILM也就无法部署。第二,许多企业不需要为云计算常用的计算类型而更长时间地管理数据,因为传统云计算通常用于功能测试/开发、概念验证(POC)、Web服务器测试等。考虑到多种因素,实施ILM策略所需细粒度的复杂性和成本与经济节省的云计算不相符。

    根据一些行业报告,70%的数据是静态的。通过将合适的数据存储在合适的介质上,企业能削减成本。他们能意识到通过部署云平台能节省成本,在云计算中实施ILM带来的经济效益意义重大。但前提是无需中断应用,而且不能增加不必要的操作复杂性。

    为了做到这些,企业必须使用基于策略的块级ILM方法,无论访问方式和应用类型。通过在数据块一级跟踪数据的属性,就无需在操作系统这一级执行数据归档或数据迁移。这种方法还能独立于操作系统类型,且独立于用于存储数据的访问方式。它不仅在保持性能(所有的数据写入都在高速层完成)的同时优化存储的成本,而且通过将不使用的数据块沉淀到低速层减少电能的消耗。这很合理,因为近线存储仅消耗企业存储的大约20%的能耗。为此,要做到真正适合企业级应用的自动分级存储,卷级或文件级数据迁移无法胜任,颗粒度必须细化到数据块级。只有数据块级的数据迁移才可能独立于操作系统类型,且独立于存储数据的访问方式,做到对应用支持的随需相应。

    四、要素4:存储访问模式

    访问存储空间有三种主流方式:基于数据块(FC SAN或iSCSI)、基于文件(CIFS/NFS)、或通过Web服务。基于块和文件的访问方式在企业应用中最常见,能更好地控制性能、可用性和安全性。在这点上,市场上大多数云计算平台利用Web服务的接口,如SOAP和REST(代表性状态传输)访问数据。虽然,这是最灵活的方式,但有性能的影响。理想的情况是,企业云提供全部的三种访问存储的方式来支持不同应用架构。

    五、要素5:可用性

    IT架构的维护窗口被大量的缩减,因为企业需要支持在不同时区的用户并保证全天候的可用性。虽然服务级别协议(SLA)一般与可用性密不可分,从业务角度看,它难以衡量,因为有着多种架构的复合SLA的重叠。

    在前面提到,在市场上大多数云计算平台中,I/O性能最先得到考虑。如果云平台依赖于不被内部IT集团管理的部分架构,那么冗余的架构部分和途径是减少停机风险的最佳方式。虽然,云存储服务提供商在考虑成本的同时继续增加可用性,但是目前市场上的服务级别协议不能满足企业关键应用的需求。

    在高端的企业级云计算中,存储系统够出来企业内的企业级存储方案,包括多路径、控制器、不同的光纤网、RAID技术、端到端的架构控制/监控,和成熟的变更管理过程。在低端的企业级云计算中,存储可用性与今天市场上云计算平台的服务水平相当。为了提供企业需要的服务水平,企业级云存储供应商必须利用健全的架构设计和被充分验证过的创新技术。

    六、要素6:主数据保护

    主数据指的是在线运行的数据。主数据能够采用单一技术,或者结合多种技术进行保护。一些常用的方法包括:RAID保护、多份拷贝、远程复制、快照、和持续数据保护。

    在市场上大多数云计算平台里,主数据保护的问题常常留给用户。今天,很少发现上述的方法在大众云计算平台中使用,因为技术的复杂性和成本。有一些大众云存储方案通过维护数据的多份拷贝来保护主数据,整个系统运行没有RAID保护的存储里,以此降低成本。

    企业级云的主数据保护应该基于内部企业级方案。当方案的业务影响分析(BIA)需要时,例如快照和容灾等可靠的技术应该就绪。

    内部企业方案和企业云存储的主要差别在于,主数据保护在方案中是如何绑定的。为了延续根据需要部署云环境的经验,各种选项必须打包,这样服务能自动部署。其结果是,将一系列绑定的选项打包,能够应对大量需求。也许不存在可以利用快照、远程复制等与客户需求相匹配的技术。无论如何,多数用户将意识到,常常需要牺牲灵活性去获取在企业云中其它的管理好处。

    :

    展开全文
  • 本文仅介绍 C++20 四大特性当中的 Module 部分,分为三部分: 探究 C++ 编译链接模型的由来以及利弊 介绍 C++20 Module 机制的使用姿势 总结 Module 背后的机制、利弊、以及各大编译器的支持情况 C++ 是兼容 C ...

    C++20 最大的特性是什么?

    最大的特性是迄今为止没有哪一款编译器完全实现了所有特性。

    文章来源:网易云信

    有人认为 C++20 是 C++11 以来最大的一次改动,甚至比 C++11 还要大。本文仅介绍 C++20 四大特性当中的 Module 部分,分为三部分:

    探究 C++ 编译链接模型的由来以及利弊

    介绍 C++20 Module 机制的使用姿势

    总结 Module 背后的机制、利弊、以及各大编译器的支持情况

    C++ 是兼容 C 的,不但兼容了 C 的语法,也兼容了 C 的编译链接模型。1973年初,C 语言基本定型:有了预处理、支持结构体;编译模型也基本定型为:预处理、编译、汇编、链接四个步骤并沿用至今;1973年,K&R 二人使用 C 语言重写了 Unix 内核。

    为何要有预处理?为何要有头文件?在 C 诞生的年代,用来跑 C 编译器的计算机 PDP-11 的硬件配置是这样的:内存:64 KiB 硬盘:512 KiB。编译器无法把较大的源码文件放入狭小的内存,故当时 C 编译器的设计目标是能够支持模块化编译,即将源码分成多个源码文件、挨个编译,以生成多个目标文件,最后整合(链接)成一个可执行文件。

    C 编译器分别编译多个源码文件的过程,实际上是一个 One pass compile 的过程,即:从头到尾扫描一遍源码、边扫描边生成目标文件、过眼即忘(以源码文件为单位)、后面的代码不会影响编译器前面的决策,该特性导致了 C 语言的以下特征:

    结构体必须先定义再使用,否则无法知道成员的类型以及偏移,就无法生成目标代码。

    局部变量先定义再使用,否则无法知道变量的类型以及在栈中的位置,且为了方便编译器管理栈空间,局部变量必须定义在语句块的开始处。

    外部变量只需要知道类型、名字(二者合起来便是声明)即可使用(生成目标代码),外部变量的实际地址由连接器填写。

    外部函数只需知道函数名、返回值、参数类型列表(函数声明)即可生成调用函数的目标代码,函数的实际地址由连接器填写。

    头文件和预处理恰好满足了上述要求,头文件只需用少量的代码,声明好函数原型、结构体等信息,编译时将头文件展开到实现文件中,编译器即可完美执行 One pass comlile 过程了。

    至此,我们看到的都是头文件的必要性和益处,当然,头文件也有很多负面影响:

    低效:头文件的本职工作是提供前置声明,而提供前置声明的方式采用了文本拷贝,文本拷贝过程不带有语法分析,会一股脑将需要的、不需要的声明全部拷贝到源文件中。

    传递性:最底层的头文件中宏、变量等实体的可见性,可以通过中间头文件“透传”给最上层的头文件,这种透传会带来很多麻烦。

    降低编译速度:加入 a.h 被三个模块包含,则 a 会被展开三次、编译三次。

    顺序相关:程序的行为受头文件的包含顺影响,也受是否包含某一个头文件影响,在 C++ 中尤为严重(重载)。

    不确定性:同一个头文件在不同的源文件中可能表现出不同的行为,导致这些不同的原因,可能源自源文件(比如该源文件包含的其他头文件、该源文件中定义的宏等),也可能源自编译选项。

    C++20 中加入了 Module,我们先看 Module 的基本使用姿势,最后再总结 Module 比 头文件的优势。

    Module(即模块)避免了传统头文件机制的诸多缺点,一个 Module 是一个独立的翻译单元,包含一个到多个 module interface file(即模块接口文件),包含 0 个到多个 module implementation file(即模块实现文件),使用 Import 关键字即可导入一个模块、使用这个模块暴露的方法。

    实现一个最简单的 Module

    module_hello.cppm:定义一个完整的hello模块,并导出一个 say_hello_to 方法给外部使用。当前各编译器并未规定模块接口文件的后缀,本文统一使用 ".cppm" 后缀名。".cppm" 文件有一个专用名称"模块接口文件",值得注意的是,该文件不光可以声明实体,也可定义实体。

    main 函数中可以直接使用 hello 模块:

    编译脚本如下,需要先编译 module_hello.cppm 生成一个 pcm 文件(Module 缓存文件),该文件包含了 hello 模块导出的符号。

    以上代码有以下细节需要注意:

    module hello:声明了一个模块,前面加一个 export,则意味着当前文件是一个模块接口文件(module interface file),只有在模块接口文件中可以导出实体(变量、函数、类、namespace等)。一个模块至少有一个模块接口文件、模块接口文件可以只放实体声明,也可以放实体定义。

    import hello:不需加尖括号,且不同于 include,import 后跟的不是文件名,而是模块名(文件名为 module_hello.cpp),编译器并未强制模块名必须与文件名一致。

    想要导出一个函数,在函数定义/声明前加一个 export 关键字即可。

    Import 的模块不具有传递性。hello 模块包含了 string_view,但是 main 函数在使用 hello 模块前,依然需要再 import ; 。

    模块中的 Import 声明需要放在模块声明之后、模块内部其他实体声明之前,即:import <iostream>; 必须放在 export module hello; 之后,void internal_helper() 之前。

    编译时需要先编译基础的模块,再编译上层模块,buildfile.sh 中先将 module_hello 编译生成 pcm,再编译 main。

    接口与实现分离

    上个示例中,接口的声明与实现都在同一个文件中(.cppm中,准确地说,该文件中只有函数的实现,声明是由编译器自动生成、放到缓存文件pcm中),当模块的规模变大、接口变多之后,将所有的实体定义都放在模块接口文件中会非常不利于代码的维护,C++20 的模块机制还支持接口与实现分离。下面我们将接口的声明与实现分别放到 .cppm 和 .cpp 文件中。

    module_hello.cppm:我们假设 say_hello_to、func_a、func_b 等接口十分复杂,.cppm 文件中只包含接口的声明(square 方法是个例外,它是函数模板,只能定义在 .cppm 中,不能分离式编译)。

    module_hello.cpp:给出 hello 模块的各个接口声明对应的实现。

    代码有几个细节需要注意:

    整个 hello 模块分成了 module_hello.cppm 和 module_hello.cpp 两个文件,前者是模块接口文件(module 声明前有 export 关键字),后者是模块实现文件(module implementation file)。当前各大编译器并未规定模块接口文件的后缀必须是 cppm。

    模块实现文件中不能 export 任何实体。

    函数模板,比如代码中的 square 函数,定义必须放在模块接口文件中,使用 auto 返回值的函数,定义也必须放在模块接口文件。

    可见性控制

    在模块最开始的例子中,我们就提到了模块的 Import 不具有传递性:main 函数使用 hello 模块的时候必须 import <string_view>,如果想让 hello 模块中的 string_view 模块暴露给使用者,需使用 export import 显式声明:

    hello 模块显式导出 string_view 后,main 文件中便无需再包含 string_view 了。

    子模块(Submodule)

    当模块变得再大一些,仅仅是将模块的接口与实现拆分到两个文件也有点力不从心,模块实现文件会变得非常大,不便于代码的维护。C++20 的模块机制支持子模块。

    这次 module_hello.cppm 文件不再定义、声明任何函数,而是仅仅显式导出 hello.sub_a、hello.sub_b 两个子模块,外部需要的方法都由上述两个子模块定义,module_hello.cppm 充当一个“汇总”的角色。

    子模块 module hello.sub_a 采用了接口与实现分离的定义方式:“.cppm” 中给出定义,“.cpp” 中给出实现。

    module hello.sub_b 同上,不再赘述。

    这样,hello 模块的接口和实现文件被拆分到了两个子模块中,每个子模块又有自己的接口文件、实现文件。

    值得注意的是,C++20 的子模块是一种“模拟机制”,模块 hello.sub_b 是一个完整的模块,中间的点并不代表语法上的从属关系,不同于函数名、变量名等标识符的命名规则,模块的命名规则中允许点存在于模块名字当中,点只是从逻辑语义上帮助程序员理解模块间的逻辑关系。

    Module Partition

    除了子模块之外,处理复杂模块的机制还有 Module Partition。Module Partition 一直没想到一个贴切的中文翻译,或者可以翻译为模块分区,下文直接使用 Module Partition。Module Partition 分为两种:

    module implementation partition

    module interface partition

    module implementation partition 可以通俗的理解为:将模块的实现文件拆分成多个。module_hello.cppm 文件:给出模块的声明、导出函数的声明。

    模块的一部分实现代码拆分到 module_hello_partition_internal.cpp 文件,该文件实现了一个内部方法 internal_helper。

    模块的另一部分实现拆分到 module_hello.cpp 文件,该文件实现了 func_a、func_b,同时引用了内部方法 internal_helper(func_a、func_b 当然也可以拆分到两个 cpp 文件中)。

    值得注意的是, 模块内部 Import 一个 module partition 时,不能 import hello:internal;而是直接import :internal; 。

    module interface partition 可以理解为模块声明拆分到多个文件中。module implementation partition 的例子中,函数声明只集中在一个文件中,module interface partition 可以将这些声明拆分到多个接口文件。

    首先定义一个内部 helper:internal_helper:

    hello 模块的 a 部分采用声明+定义合一的方式,定义在 module_hello_partition_a.cppm 中:

    hello 模块的 b 部分采用声明+定义分离的方式,module_hello_partition_b.cppm 只做声明:

    module_hello_partition_b.cpp 给出 hello 模块的 b 部分对应的实现:

    module_hello.cppm 再次充当了”汇总“的角色,将模块的 a 部分+ b 部分导出给外部使用:

    module implementation partition 的使用方式较为直观,相当于我们平时编程中“一个头文件声明多个 cpp 实现”这种情况。module interface partition 有点类似于 submodule 机制,但语法上有较多差异:

    module_hello_partition_b.cpp 第一行不能使用 import hello:partition_b;虽然这样看上去更符合直觉,但是不允许。

    每个 module partition interface 最终必须被 primary module interface file 导出,不能遗漏。

    primary module interface file 不能导出 module implementation file,只能导出 module interface file,故在 module_hello.cppm 中 export :internal; 是错误的。

    同样作为处理大模块的机制,Module Partition 与子模块最本质的区别在于:子模块可以独立的被外部使用者 Import,而 Module Partition 只在模块内部可见。

    全局模块片段

    (Global module fragments)

    C++20 之前有大量的不支持模块的代码、头文件,这些代码实际被隐式的当作全局模块片段处理,模块代码与这些片段交互方式如下:

    事实上,由于标准库的大多数头文件尚未模块化(VS 模块化了部分头文件),整个第二章的代码在当前编译器环境下(Clang12)是不能直接编译通过的——当前尚不能直接 import < iostream > 等模块,通全局模块段则可以进行方便的过渡(在全局模块片段直接 #include <iostream>),另一个过渡方案便是下一节所介绍的 Module Map——该机制可以使我们能够将旧的 iostream编译成一个 Module。

    Module Map

    Module Map 机制可以将普通的头文件映射成 Module,进而可以使旧的代码吃到 Module 机制的红利。下面便以 Clang13 中的 Module Map 机制为例:

    假设有一个 a.h 头文件,该头文件历史较久,不支持 Module:

    通过给 Clang 编译器定义一个 module.modulemap 文件,在该文件中可以将头文件映射成模块:

    编译脚本需要依次编译 A、ctype、iostream 三个模块,然后再编译 main 文件:

    首先使用 -fmodule-map-file 参数,指定一个 module map file,然后通过 -fmodule 指定 map file 中定义的 module,就可以将头文件编译成 pcm。main 文件使用 A、iostream 等模块时,同样需要使用 fmodule-map-file 参数指定 mdule map 文件,同时使用 -fmodule 指定依赖的模块名称。

    注:关于 Module Map 机制能够查到的资料较少,有些细节笔者也未能一一查明,例如:

    通过 Module Map 将一个头文件模块化之后,头文件中暴露的宏会如何处理?

    假如头文件声明的实体的实现分散在多个 cpp 中,该如何组织编译?

    Module 与 Namespace

    Module 与 Namespace 是两个维度的概念,在 Module 中同样可以导出 Namespace:

    总结

    最后,对比最开始提到的头文件的缺点,模块机制有以下几点优势:

    无需重复编译:一个模块的所有接口文件、实现文件,作为一个翻译单元,一次编译后生成 pcm,之后遇到 Import 该模块的代码,编译器会从 pcm 中寻找函数声明等信息,该特性会极大加快 C++ 代码的编译速度。

    隔离性更好:模块内 Import 的内容,不会泄漏到模块外部,除非显式使用 export Import 声明。

    顺序无关:Import 多个模块,无需关心这些模块间的顺序。

    减少冗余与不一致:小的模块可以直接在单个 cppm 文件中完成实体的导出、定义,但大的模块依然会把声明、实现拆分到不同文件。

    子模块、Module Partition 等机制让大模块、超大模块的组织方式更加灵活。

    全局模块段、Module Map 制使得 Module 与老旧的头文件交互成为可能。

    缺点也有:

    编译器支持不稳定:尚未有编译器完全支持 Module 的所有特性、Clang13 支持的 Module Map 特性不一定保留到主干版本。

    编译时需要分析依赖关系、先编译最基础的模块。

    现有的 C++ 工程需要重新组织 pipline,且尚未出现自动化的构建系统,需要人工根据依赖关系组构建脚本,实施难度巨大。

    Module 不能做什么?

    Module 不能实现代码的二进制分发,依然需要通过源码分发 Module。

    pcm 文件不能通用,不同编译器的 pcm 文件不能通用,同一编译器不同参数的 pcm 不能通用。

    无法自动构建,现阶段需要人工组织构建脚本。

    编译器如何实现对外隐藏 Module 内部符号的?

    在 Module 机制出现之前,符号的链接性分为外部连接性(external linkage,符号可在文件之间共享)、内部链接性(internal linkage,符号只能在文件内部使用),可以通过 extern、static 等关键字控制一个符号的链接性。

    Module 机制引入了模块链接性(module linkage),符号可在整个模块内部共享(一个模块可能存在多个 partition 文件)。

    对于模块 export 的符号,编译器根据现有规则(外部连接性)对符号进行名称修饰(name mangling)。

    对于 Module 内部的符号,统一在符号名称前面添加 “_Zw” 名称修饰,这样链接器链接时便不会链接到内部符号。

    截至2020.7,三大编译器对 Module 机制的支持情况:

    以上就是本文的全部内容,关于 C++20 的四大特性我们介绍了其一

    写在最后:其实每个人都有自己的选择,学编程,每一种编程语言的存在都有其应用的方向,选择你想从事的方向,去进行合适的选择就对了!对于准备学习编程的小伙伴,如果你想更好的提升你的编程核心能力(内功)不妨从现在开始!

    C语言C++编程学习交流圈子,QQ群:614504899点击进入】微信公众号:C语言编程学习基地

    整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)

    欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

    编程学习视频分享:

     

    展开全文
  • Spring 与自定义注解、外部配置化的结合使用一、Java注解的简单介绍注解,也叫Annotation、标注,是 Java 5 带来的新特性。可使用范围类、字段、方法、参数、构造函数、包等,具体可参阅枚举类 java.lang.annotation...
  • 导读:C++20 标准早已封版,各大编译器也都已支持了 C++20 中的多数特性,但迄今为止(2021.7),尚未有哪一款编译器完整支持 C++20 中的所有特性。本文仅介绍 C++20 ...
  • Spark是一种基于内存的、分布式的、大数据处理框架,在 Hadoop 的强势之下,Spark凭借着快速、简洁易用、通用性以及支持多种运行模式四大特征,冲破固有思路成为很多企业标准的大数据分析框架。1 快速面向磁盘的...
  • Oracle Database 18c支持将外部表中的数据填充到内存列存储...在Exadata上运行的Oracle Database 19c环境中,对外部表使用IM列存储进行了增强,如果启用了内存的外部表功能,就会自动将外部数据填充到IM列存储中。...
  • 【解析题】保护计算机网络设备免受环境事故的影响属于信息安全的哪个方面? 【解析题】把内存中的数据传送到计算机的硬盘,称为___________。 【解析题】计算机病毒是利用在网络中达到不断扩散的目的。 【解析题】...
  • 逻辑工作单元要成为事务,在关系型数据库管理系统中,必须满足 4 个特性 原子性 : 事务的所有操作,要么全部完成,要么全部不完成,不会结束在某个中间环节 一致性 : 事务开始之前和事务结束之后,数据库的完整...
  • 这台电脑有哪些特点,相较以往有了哪些进步,今天我们将从4方面来进行探讨。电池续航更长了联想ThinkPadX240的续航能力原本已经令人满意,联想ThinkPadX250的续航能力更上一层楼。联想ThinkPadX250采用了...
  • 2,实现一最简单的module 3,接口与实现分离 module接口文件(后缀名)、module实现文件 4,可见性控制 5,子模块(submodule) 6,模块拆分(module partition) 2,concept 带约束的T 函数模板缩写 ...
  • Java开发环境的配置

    2021-02-26 17:57:29
    第一阶段 JAVA基础知识第一章 开发环境的配置知识铺垫:Dos 命令在正式进入Java学习之前我们来了解一看起来B格很高的东西——Dos命令DOS命令,计算机术语,是指DOS操作系统的命令,是一种面向磁盘的操作命令,主要...
  • 作为一开发者,有一学习的氛围跟一交流圈子特别重要,这是一我的iOS交流群:812157648,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长! Block在OC中的...
  • JAVA基础—— 面向对象的三大特性以及配置环境 三大性质 1. 封装 2. 继承 3. 多态
  • -------------------------------------------------------------------------------------------------------------------------------------bash shell的命令分为两类:外部命令和内部命令。外部命令是通过系统...
  • 文章目录操作系统的发展和分类举例对比单批道处理和多批道处理总结操作系统的功能和目标提供的功能作为系统资源的管理者为用户提供使用硬件设备的接口作为最接近硬件的层次总结操作系统的四个特征并发共享虚拟异步...
  • 记录一咸鱼大学生三月的奋进生活019复习Java(I/O流)流的分类节点流和处理流字节流(Stream)1、文件字节传输流【节点流】2、对象字节传输流【处理流】3、数据字节传输流【处理流】4、PrintStream(标准流)...
  • 软件质量模型的六大特性27个子特性一、功能性(Functionality):1、适合性(Suitability):解释有没有-提供了相应的功能2、准确性(accuracy):正确(用户需要的)解释对不对3、互操作性(Interoperability):产品与产品...
  • php是什么? PHP是PHP:HypertextPreprocessor(超文本预处理器)的首字母缩写,是一种跨平台的、开源的、免费的脚本语言,其语法吸收了C语言、... ...php环境搭建 系统 集成工具 编辑器 windows phpStudy/phpEnv/up
  • 构建验证环境的内经

    2021-02-26 16:17:56
    在发送测试序列之前,首先需要创建一个结构化的环境,将环境建立的核心要素拆解开来,可以分为四个部分: 单元组件的自闭性 回归创建 通信端口连接 顶层配置 二、单元组件的自闭性 自闭性指的是单元组件(例如uvm_...
  • 职业生涯规划书一、社会环境规划和职业分析计算机应用的特殊社会环境计算机的应用领域已渗透到社会的各行各业,正在改变着传统的工作、学习和生活方式,推动着社会的发展。从计算机行业应用市场的结构特征来看。目前...
  • Linux 环境变量(基础)

    2021-03-30 16:35:14
    bash shell用一叫作环境变量( environment variable)的特性来存储有关shell会话和工作环 境的信息(这也是它们被称作环境变量的原因)。这项特性允许你在内存中存储数据,以便程序 或shell中运行的脚本能够轻松...
  • 本系列博客包括6专栏,分别为:《自动驾驶技术概览》、《自动驾驶汽车平台技术基础》、《自动驾驶汽车定位技术》、《自动驾驶汽车环境感知》、《自动驾驶汽车决策与控制》、《自动驾驶系统设计及应用》,笔者不是...
  • 1、开发第一java程序:HelloWorldpublic class HelloWorld{ // 这是一类,类名叫做HelloWorldpublic static void main(String[] args){ //主方法入口System.out.println("Hello World");System.out.println("我...
  • 有一些直接通过命令执行的)2 Java语言概述什么是计算机语言关于面向对象和面向过程java特性3 Java程序运行机制4 Java语言环境的搭建5 开发体验HelloJava6 小结第一程序7 常见问题及解决方法8 注释 1基础常识 软件...
  • 现代城市生态与环境

    千次阅读 2021-03-27 13:40:07
    绪论(一)已完成本次成绩:100 1 【单选题】 相较于乡村环境,城市的主要问题不包括()。 窗体顶端 A、 交通拥挤  B、 ...自然环境丰富 ...【单选题】构成城市的三要素是()。 窗体顶端 A、地理、人口
  • 第三章 5G的四大特征 (内在) 3.1 泛在(网络自身的存在) 3.2 低功耗 3.3 网络虚拟化 3.4 网络智能化 第章 5G关键的技术(内在技术) 4.1 无线接入技术 4.2 网络重构技术 4.3分布式业务服务 第五章 5G...
  • A 原生环境和次生环境 B 生存环境和生产环境 C 自然环境和人工环境 D 生活环境和生态环境 3.提出“可持续发展”战略的联合国会议和文件是( ) A 1972年斯德歌尔摩人类环境会议通过的《人类环境宣言》 B 1982年...
  • 【解析题】计算机网络按照地域进行划分,可以分为() 【解析题】利用某些元件感觉外部环境将信息传送到芯片中进行处理,使机器人能够灭火、踢足球等活动,这些用以感觉外部环境的元件是利用计算机技术制造的 【解析题...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 143,454
精华内容 57,381
关键字:

外部环境的四个特性