为什么应该用模块取代C/C++中的头文件?

摘要:本文整理自Apple C++工程师Doug Gregor的演讲Slide,他表示希望使用模块(Module)这一概念替代C/C++中的头文件,现已被C++标准化委员会任命为Module研究组的主席,研究该提议的可能性。考虑到Apple的开源项目LLVM在编辑器领域中的地位,这一提议非常值得重视。

为什么应该使用模块(Module)替代头文件(Header)?

头文件糟透了!


众所周知,C程序在编译时一般会预处理头文件:

常规解决办法如下:

  1. LLVM_WHY_PREFIX_UPPER_MACROS 
  2.     LLVM_CLANG_INCLUDE_GUARD_H 
  3.     template<class _Tp> 
  4.  
  5. const _Tp& min(const _Tp &__a, 
  6.                const _Tp &__b); 
  7.  
  8. #include <windows.h> 
  9. #undef min // because #define NOMINMAX 
  10. #undef max // doesn’t 

但结果依然不够理想,比较一下代码与程序大小你会发现:

另外,头文件形式的可扩展性天生不足。假设有n个源文件,每个源文件引用了m个头文件,那么构建过程的开销会是m×n。这在C++中表现得尤为糟糕。所以预说处理头文件是一个非常糟糕的解决方案。

C家族的模块系统

模块是什么?

  • 库的接口(API)
  • 库的实现

使用“import”导入已命名的模块:

import会在源文件中忽略预处理状态,并且选择性导入,所以弹性(resilience)非常好。

使用“import”会导入什么?

  • 函数、变量、类型、模板、宏,等等;
  • 公开API——其它的都隐藏;
  • 没有特别的命名空间机制。

C/C++引入模块会怎么样?


引入模块的目标在于:

  • 在源文件中指定模块名称;
  • API公开;
  • 没有头文件!

要编写一个模块非常简单,只需要使用export:

但是这么做会遇到很多遗留问题:

  • 需要迁移现在基于头文件的类库;
  • 与不支持模块的编译器的互操作性;
  • 工具需要理解模块;

所以应该使用引入模块的过渡方案——直接从头文件中构建模块。这么做有以下好处:

  • 头文件有利于互操作;
  • 程序员不需要完全改变自己习惯的开发模式;

模块地图(Module Map)

模块地图是模块的关键,用来定位模块相关(子)模块,包含以下功能:

  • 模块定义命名(子)模块

  • 头文件在(子)模块中包含命名头文件的内容

保护伞头文件(Umbrella Header)

  • 保护伞头文件会在其目录下包含所有头文件信息
  • 使用通配符submodules (module *) 可以为每一个包含的头文件创建一个子模块:
    1. AST/Decl.h -> ClangAST.Decl 
    2. AST/Expr.h -> ClangAST.Expr 

模块编译过程:

  1. 找到命名模块的module map;
  2. 产生一个独立编译器实例;
  3. 在module map中解析头文件。

编辑模块文件过程:

  1. 在“import”声明处导入模块文件;
  2. 把模块文件保存在缓存中待重用。

从头文件到模块化


从头文件编程转换到使用模块非常简单:

库方面:合并复合定义的结构、函数、宏,并且为头文件导入依赖,最后编写好模块地图;

开发者方面只需要从“#include”过渡到“import”:

  1. 把“#inlude”都换成“import”;
  2. 使用module maps确定(子)模块(类似头文件里的“#include”);

当然,你也可以使用工具来自动化重写代码,非常简单。

工具


编辑性能

使用模块能够提升语法解析性能:

  • 模块化的头文件只需要解析一次,之后放在缓存中,于是m×n --> m+n
  • 所有基于源(source-based)工具都能带来好处
  • 自动链接大大简化了库的使用

  • 自动导入可以阻止“#include”带来的可怕的调试结果

调试流

通过DWARF的双程调试有损耗:

  • 只能获得“用过”类型和函数
  • 丢失了行内函数、模板

另外调试过程还会出现信息冗余

使用模块的调试又会怎样?

1.提高了构建性能

  • 编译器发出的DWARF更少
  • 链接器清除重复的DWARF也更少

2.提高了调试体验

  • 调试器的ASF精度非常完美
  • 调试器不需要寻找DWARF

总结


总而言之,C/C++使用模块化非常有潜力:

  • 编译/构建时间的缩短
  • 修复各种预处理问题
  • 更好的工具体验
  • 通过设计,能够平稳地过渡
  • Clang实现已经在进行了

这个Slide在Hacker News上引起了激烈讨论,大部分网友还是赞成模块化的方式:

baberman:对我来说没什么不便,而且还给出了过渡方案,可能会很适合某些C/C++项目。我们应该对任何提升C/C++性能的想法持开放态度。

greggman:预处理有什么不好吗?如果我不想用预处理,我完全可以使用Objective-C等。现在的机器性能已经够强大了,import在编译上的性能优势对我来说没有任何吸引力,我更喜欢C/C++的传统方式。

msbarnett反驳greggman:我认为这正是这份提议的精髓所在,你既可以保留使用#include,也可以从现在开始就转向import模块的方式。

_djo_:这个想法会非常有前途!要说缺点的话就是来得太迟了!

nkurz:我不同意“m个头文件+n个源文件 --> m×n倍编译性能”。只要使用“#ifndef _HEADER_H”就不会出现这个问题,或者,为什么不使用#include_once <header.h>来解决呢?预处理很可怕吗?预处理确实有一些问题,但是却是可以克服的。

SeoxyS:我不关心性能,现在性能已经不是问题了,我更关心怎样给开发者更少的负担。

各位CSDN网友是怎样看的呢?欢迎一起讨论。

相关链接:Doug的Slide、Hacker News上的讨论

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

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

相关文章

Kong Api 初体验、Kong安装教程

见&#xff1a;https://blog.csdn.net/forezp/article/details/79383631Kong是一个可扩展的开源API层&#xff08;也称为API网关或API中间件&#xff09;。 Kong运行在任何RESTful API的前面&#xff0c;并通过插件扩展&#xff0c;它们提供超出核心平台的额外功能和服务。 Kon…

从谷歌宕机事件认识互联网工作原理

摘要&#xff1a;谷歌服务器经历了短暂的宕机事件&#xff0c;持续大概27分钟&#xff0c;对部分地区的互联网用户造成了影响。此次事件的原因深究起来需要进入互联网络那深邃的、黑暗的角落。 译者注&#xff1a;本文中提到CloudFlare是一家总部位于美国旧金山的内容分发网络(…

推荐给开发人员的实用命令行工具

摘要&#xff1a;优秀的工具对于定位问题出在何处有着无可估量的价值&#xff0c;而且能在一开始就帮助我们阻止问题的出现&#xff0c;总的来说能使我们的工作更有效率。本文介绍了6个非常强大且灵活的工具&#xff0c;熟练使用这些工具能使你的生活变得更轻松一些。 作为一名…

雷军:启动手机+AIoT双引擎战略 5G春天到来前打持久战

雷帝网 乐天 1月11日报道 小米CEO雷军今日在小米年会上宣布&#xff0c;2019年&#xff0c;小米将正式启动“手机AIoT”双引擎战略&#xff0c;这将是小米未来五年的核心战略。未来5年&#xff0c;小米将在AIoT领域持续投入超过100亿元。从2019年起&#xff0c;AIoT&#xff0c…

Jenkins自定义主题

x下载自定义样式 http://afonsof.com/jenkins-material-theme/ 打开连接 最后点击&#xff1a;DOWNLOAD TOUR THEME! 得到样式文件&#xff1a;jenkins-material-theme.css 上传样式文件到jenkins 将jenkins-material-theme.css 上传到&#xff1a; /var/jenkins_home/userCont…

SSH (Secure Shell)详解

Secure Shell&#xff08;SSH&#xff09;是一种加密 网络协议&#xff0c;用于在不安全的网络上安全地运行网络服务。 SSH通过客户端 - 服务器体系结构中的不安全网络提供安全通道&#xff0c;将SSH客户端应用程序与SSH服务器相连接。 常见的应用程序包括远程命令行登录和远程…

2021-08-12 画蜡烛线

画蜡烛线 pip install https://github.com/matplotlib/mpl_finance/archive/master.zip from mpl_finance import candlestick_ochl import matplotlib.pyplot as plt from matplotlib.pylab import date2num# 先画日K线 fig, axes plt.subplots(nrows1, ncols1, figsize(20, …

通达信获取数据

#python第三方库pytdx获取 from pytdx.hq import TdxHq_API api TdxHq_API() # 数据获取接口一般返回list结构&#xff0c;如果需要转化为pandas Dataframe接口&#xff0c;可以使用 api.to_df 进行转化 with api.connect(119.147.212.81, 7709): # 返回普通list data …

股票数据相关性分析

导入相关包 import pandas as pd import numpy as np import matplotlib.pyplot as plt from matplotlib.collections import LineCollection import akshare as ak from sklearn import cluster, covariance, manifold %matplotlib inline #Jupyter Notebook显示图形专用 plt…

分享一个辅助分析内存泄漏的脚本

最近给系统做了一点优化&#xff0c;前几天去查看系统监控&#xff0c;想看看上线前后cpu使用率曲线变化情况。查看的时候意外发现上线前后内存占用相差不少&#xff0c;20%以上。 本来我没怎么在意这个问题&#xff0c;因为我们系统会在运行过程中缓存部分数据内容。但客户觉得…

专访刘伟:软件开发人员的内功修炼之道

摘要&#xff1a;数学修养对软件开发之路起着什么作用&#xff1f;码农如何修炼自己的内功并成长为优秀的软件开发员&#xff1f;带着相关思考&#xff0c;社区之星第10期采访了中南大学副教授——刘伟。他对数学修养、设计模式、软件架构和重构方面的独特见解&#xff0c;相信…

地址解析协议 (ARP) 是什么

地址解析协议 (ARP) 是通过解析网路层地址来找寻数据链路层地址的一个在网络协议包中极其重要的网络传输协议。 ARP是通过网络地址(例&#xff1a;IPv4)来定位MAC地址 (也称为乙太地址)。 ARP已经在很多网路层和数据链接层之间得以实现&#xff0c;包括IPv4&#xff0c;Chaosn…

04.React事件 方法、 React定义方法的几种方式 获取数据 改变数据 执行方法传值...

2019独角兽企业重金招聘Python工程师标准>>> 一.基本用法 在以类继承的方式定义的组件中&#xff0c;为了能方便地调用当前组件的其他成员方法或属性&#xff08;如&#xff1a;this.state&#xff09;&#xff0c;通常需要将事件处理函数运行时的 this 指向当前组件…

代码之美——Doom3源代码赏析

摘要&#xff1a;Dyad作者、资深C工程师Shawn McGrathz在空闲时翻看了Doom3的源代码&#xff0c;发出了这样的惊叹&#xff1a;“这是我见过的最整洁、最优美的代码&#xff01;”“Doom 3的源代码让我对那些优秀的程序员刮目相看。”因此有了本文。 背景介绍&#xff1a; Doom…

文件基本处理

1 打开文件&#xff0c;将文件句柄赋值给一个变量 2 拿句柄对文件进行操作 3 关闭文件 将一个文件第一行写道另外一个文件 f open("test","r",encoding"utf-8") # open找的是系统的编码 x f.readlines() f.close() f1 open("test1"…

代码审查:程序员内炼之道

摘要&#xff1a;“关注并弄清楚桥梁修建细节&#xff0c;否则你建起来的桥梁有可能坍塌。”代码审查更重要的是一种技术分享或者代码共享。程序员如何提升自我修炼之道&#xff0c;欢迎来支招。 代码审查更重要的是一种技术分享或者代码共享。在审查过程中&#xff0c;通过被…

排序代码(python,c++) 及 基本算法复杂度

0.导语 本节为手撕代码系列之第一弹&#xff0c;主要来手撕排序算法&#xff0c;主要包括以下几大排序算法&#xff1a; 直接插入排序 冒泡排序 选择排序 快速排序 希尔排序 堆排序 归并排序 1.直接插入排序 【算法思想】 每一步将一个待排序的记录&#xff0c;插入到前面…

TCP/IP四层模型与OSI参考模型

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 TCP/IP四层模型&#xff1a; 1.链路层&#xff08;数据链路层/网络接口层&#xff09;&#xff1a;包括操作系统中的设备驱动程序、计算…

还驾驭不了4核? 别人已模拟出百万核心上的并行

摘要&#xff1a;不管是台式机还是笔记本&#xff0c;四核双核都已经不是新鲜的事了。计算机领域的你可能已经认识到了给电脑选配4核的处理器完全是一种浪费&#xff0c;因为大多数的程序都不支持多核心的并行处理。然而斯坦福的计算机科学家最近公布&#xff0c;他们已经模拟出…

Django内置权限扩展案例

当Django的内置权限无法满足需求的时候就自己扩展吧~ 背景介绍 overmind项目使用了Django内置的权限系统&#xff0c;Django内置权限系统基于model层做控制&#xff0c;新的model创建后会默认新建三个权限&#xff0c;分别为&#xff1a;add、change、delete&#xff0c;如果给…