为什么 C# 比 C++ 编译快那么多
Go 我不懂,下面以 C++ 和 C# 对比来说明为什么 C++ 编译慢和 C# 编译快。
C 和 C++ 文件的编译经过几个主要步骤:
- 处理续行符处理(“\”)之类的杂事
- 词法分析,解析出 tokens 来
- 预处理,宏展开,处理 #include ,然后对 #include 包含的文件又重复 1~3 步骤。
- 重新词法分析
- 语法分析生成抽象语法树 AST
- 语义分析
- 优化生成代码
C# 的步骤:
- 处理续行符处理(“\”)之类的杂事
- 词法分析,解析出 tokens 来
- 语法分析生成抽象语法树 AST
- 语义分析
- 优化生成代码
首先,直观的看,从编译阶段上来说 C# 就比 C++ 少,这是一个原因。
另一个原因是语言的编译速度跟语法关系很大,高级语言编译一般是经过词法分析=>语法分析=>语义分析=>优化生成代码几步,如果语言的语法上没有歧义,编译的每个阶段都是独立的,那么编译速度自然就快。
如果不是这样,语法上有歧义,比如 C++ 嵌套模板的">>"和位操作的“>>”,当编译器遇到嵌模板">>"的时候只有先放着,然后往前多看几步才能确定到底是模板的尖括号还是移位,自然比没有语法歧义的语言要慢啦。
再举个例子,C++调用模板函数实例化时可以省略<>让编译器自己去推导最合适的重载,C# 泛型方法调用也可以省略 <>。类似这样的语法元素使得编译器在语法分析阶段就不能够确定一个函数调用是否是函数模板实例化(对于 C# 来说是泛型方法调用)还是一个普通的函数调用,而要等到语义分析阶段才能确定,所以在这一点上 C++ 和 C# 其实都选择牺牲编译速度来为人类减少击键次数做贡献并略微提高了代码的可读性。
还有一个方面是C和C++的编译时代码生成问题产生的:头文件和宏定义会在编译时生成代码,宏展开和引入头文件相当于硬插入了一大段文本,让编译器需要重新从词法分析开始分析,模板什么的虽然不是直接插入文本,但处理起来也很麻烦,消耗了不少的编译时间。如果 C/C++ 不是用头文件而是某种形式的编译模块,多个源文件(编译单元)引用同一个模块那么编译器只需分析一次该模块生成 AST 反复使用,那编译速度也能提升不少。
比起 C/C++ 笨笨的文本插入形式的 #include,C# 编译器完全省去了头文件的编译,你引用的 assembly 直接提供了类型和方法神马的元数据,编译器直接拿来用就好。
最后,因为 C# 没有宏和模板之类的代码生成手段,泛型也是运行时处理的,进一步加快了编译速度。
----------
题外话
关于编译器自举跟编译速度关系不大,目前(VS2013)的 C# 编译器应该是 C++ 写的,编译速度很快,但是 Mono 的编译器是 C# 写的,感觉并不慢,至少没有数量级上的差异。现在连 M$ 新的 C# 编译器 Rosylin 也完全用 C# 写了,还很模块化,性能也不差哦。
说了这么多,其实我的意思是 C++ 和 C# 比 PHP 的编译速度差远了,PHP 是最好的语言!
为什么 C# 比 C++ 编译快那么多的更多相关文章
- 让QT编译快一点(增加基础头文件)
姚冬,中老年程序员 进藤光.杨个毛.欧阳修 等人赞同 我是来反对楼上某些答案的.我曾经用MFC写了金山词霸(大约20多万行),又用Qt写了YY语音(大约100多万行),算是对两种框架都比较有经验.纠正 ...
- 为什么golang的开发效率高(编译型的强类型语言、工程角度高、在开发上的高效率主要来自于后发优势,编译快、避免趁编译时间找产品妹妹搭讪,既是强类型语言又有gc,只要通过编译,非业务毛病就很少了)
作者:阿猫链接:https://www.zhihu.com/question/21098952/answer/21813840来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- 2020年使用Delphi的25个理由(我觉得四个优点:控件+可视化开发+跨平台+数据库,还有一个编译快,运行快)——人生苦短,我用Delphi!
25年后从10个使用Delphi的理由到1个至25个使用Delphi 10.3的理由 25年前发布Delphi 1时,我汇总了使用Delphi的十大理由.这是我精通Delphi原始书的序言中的原始列表 ...
- iOS: FFMpeg编译和使用问题总结
iOS: FFmpeg编译和使用问题总结 折磨了我近一周多时间的FFmpeg库编译问题终于解决了,必须得把这一段时间来遇到过的坑全写出来.如果急着解决问题,编译最新版本的FFmpeg库请直接看第二部分 ...
- C/C++的编译器|编译环境(非常全面的比较)
C/C++编译器的一些易混淆概念,总结一下. 关于什么是Unix-like操作系统,常见操作系统间差异,什么是操作系统接口等等,请参考<操作系统宝鉴>. C/C++编译器有哪些? 首先是如 ...
- Delphi的核心优势:三快一多
快是指:开发快(RAD开发),编译快(好像是没有用到LL(1),从而避免了潜在的歧义),运行快(原生代码). 多是指:开发符合PME标准的可视化控件,易开发,易使用,所以第三方控件特别多,这个不用解释 ...
- 尝试在CentOS7.2上编译安装Swift
苹果提供 Ubuntu上构建Swift 的教程,通过这个教程我尝试使用CentOS7.2上玩儿一把.目前已经成功在CentOS7.2上班成功安装 swift 4.0 https://github.co ...
- iOS: FFmpeg编译和使用 学习
ffmpeg是一个多平台多媒体处理工具,处理视频和音频的功能非常强大.目前在网上搜到的iOS上使用FFMPEG的资料都比较陈旧,而FFMPEG更新迭代比较快: 且网上的讲解不够详细,对于初次接触FFM ...
- 全图化引擎(AI·OS)中的编译技术
全图化引擎又称算子执行引擎,它的介绍可以参考从HA3到AI OS -- 全图化引擎破茧之路.本文从算子化的视角介绍了编译技术在全图化引擎中的运用.主要内容有: 1. 通过脚本语言扩展通用算子上的用户订 ...
随机推荐
- 开源性能测试工具Locust使用篇(一)
1. 环境准备 安装python3.6 ,安装步骤略 pip install locust 安装完成后使用locust -V检查 2.locust使用,先编辑一个简单的load_test.py的脚本 ...
- 机器学习技法笔记:09 Decision Tree
Roadmap Decision Tree Hypothesis Decision Tree Algorithm Decision Tree Heuristics in C&RT Decisi ...
- 什么是Spring Boot?
什么是Spring Boot? Spring Boot是Spring开源组织下的子项目,是Spring组件一站式解决方案,主要是简化了使用Spring的难度,简省了繁重的配置,提供了各种启动器,开发者 ...
- 解决Eclipse中DDMS一直打印输出Connection attempts的问题
Eclipse/MyEclipse出现以下错误的解决方案: [2015-01-25 16:10:29 - DeviceMonitor] Adb connection Error:远程主机强迫关闭了一个 ...
- kafka shutdown停止关闭很慢问题的解决方案
kafka shutdown停止很慢问题 在数据量大的时候,consumer一次抓取数据的数据很多,进入到业务处理的数据可能有很多, 假设一次poll有1万条数据进入业务程序,而且业务程序是和poll ...
- CentOS 部署 NodeBB
0x00 前言 NodeBB 是基于 NodeJS 的开源 BBS 系统,可以搭配 redis 或 mongodb 数据库,本文中由于使用 NodeBB 配置中默认的 npm 安装会引起不知原因的 5 ...
- SQL 必知必会·笔记<16>使用视图
1.视图 视图是虚拟的表.与包含数据的表不一样,视图只包含使用时动态检索数据的查询. 为什么使用视图 重用SQL 语句 简化复杂的SQL 操作.在编写查询后,可以方便地重用它而不必知道其基本查询细节 ...
- Spring Boot + Spring Cloud 构建微服务系统(九):配置中心(Spring Cloud Config)
技术背景 如今微服务架构盛行,在分布式系统中,项目日益庞大,子项目日益增多,每个项目都散落着各种配置文件,且随着服务的增加而不断增多.此时,往往某一个基础服务信息变更,都会导致一系列服务的更新和重启, ...
- Dockerfile指令详解
Dockerfile中包括FROM.MAINTAINER.RUN.CMD.EXPOSE.ENV.ADD.COPY.ENTRYPOINT.VOLUME.USER.WORKDIR.ONBUILD等13个指 ...
- kafka集群管理
1.启动kafka集群 kafka 没有提供同时启动集群中所有节点的执行脚本,这里自定义一个脚本 名称为 kafka-cluster-start.sh 2.关闭节点 kafka自带关闭脚本 kafka ...