为什么 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. 通过脚本语言扩展通用算子上的用户订 ...
随机推荐
- redis key的过期时间
设置redis key的生存过期时间 Redis 有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除) : EXPlRE 命令用于将键key 的生存时间设置为tt ...
- python基础的几个小练习题
题目: 1.写一个程序,判断2008年是否是闰年. 2.写一个程序,用于计算2008年10月1日是这一年的第几天?(2008年1月1日是这一年的第一天) 3.(文件题)有一个“record.txt”的 ...
- Android开发之漫漫长途 XIX——HTTP
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- openshift上使用devicemapper
环境:openshift v3.6.173.0.5 openshift上devicemapper与官方文档中的描述略有不同,在官方文档的描述中,容器使用的lvm文件系统挂载在/var/lib/devi ...
- JavaWeb学习 (六)————Servlet(二)
一.ServletConfig讲解 1.1.配置Servlet初始化参数 在Servlet的配置文件web.xml中,可以使用一个或多个<init-param>标签为servlet配置一些 ...
- Go语言学习笔记(一) [Go语言的HelloWorld]
日期:2014年7月18日 1.简介 Go 编程语言是一个使得程序员更加有效率的开源项目.Go 是有表达力.简 洁.清晰和有效率的.它的并行机制使其很容易编写多核和网络应用,而新奇的类型系 ...
- Spark新手入门——1.Scala环境准备
主要包括以下三部分,本文为第一部分: 一. Scala环境准备 二. Hadoop集群(伪分布模式)安装 查看 三. Spark集群(standalone模式)安装 查看 因Spark任务大多由Sca ...
- .12-浅析webpack源码之NodeWatchFileSystem模块总览
剩下一个watch模块,这个模块比较深,先大概过一下整体涉及内容再分部讲解. 流程图如下: NodeWatchFileSystem const Watchpack = require("wa ...
- session持久化到sqlserver
每次想使用都会忘记单词,所幸记录下来.简单步骤记录. 第一步:找到cmd目录 输入:cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 进入该目录. 第二 ...
- 2.C++中的bool类型,三目运算符,引用
本章主要内容: 1)bool类型 2)三目运算符 3)引用 1.布尔型bool 在C++中,bool类型只有true(非0)和flase(0)两个值,且bool类型只占用了一个字节. 例如: #inc ...