为什么应该用模块取代C/C++中的头文件?
為什么應該使用模塊(Module)替代頭文件(Header)?
頭文件糟透了!
眾所周知,C程序在編譯時一般會預處理頭文件:
常規(guī)解決辦法如下:
但結果依然不夠理想,比較一下代碼與程序大小你會發(fā)現(xiàn):
另外,頭文件形式的可擴展性天生不足。假設有n個源文件,每個源文件引用了m個頭文件,那么構建過程的開銷會是m×n。這在C++中表現(xiàn)得尤為糟糕。所以預說處理頭文件是一個非常糟糕的解決方案。
C家族的模塊系統(tǒng)
模塊是什么?
- 庫的接口(API)
- 庫的實現(xiàn)
使用“import”導入已命名的模塊:
import會在源文件中忽略預處理狀態(tài),并且選擇性導入,所以彈性(resilience)非常好。
使用“import”會導入什么?
- 函數(shù)、變量、類型、模板、宏,等等;
- 公開API——其它的都隱藏;
- 沒有特別的命名空間機制。
C/C++引入模塊會怎么樣?
引入模塊的目標在于:
- 在源文件中指定模塊名稱;
- API公開;
- 沒有頭文件!
要編寫一個模塊非常簡單,只需要使用export:
但是這么做會遇到很多遺留問題:
- 需要遷移現(xiàn)在基于頭文件的類庫;
- 與不支持模塊的編譯器的互操作性;
- 工具需要理解模塊;
所以應該使用引入模塊的過渡方案——直接從頭文件中構建模塊。這么做有以下好處:
- 頭文件有利于互操作;
- 程序員不需要完全改變自己習慣的開發(fā)模式;
模塊地圖(Module Map)
模塊地圖是模塊的關鍵,用來定位模塊相關(子)模塊,包含以下功能:
- 模塊定義命名(子)模塊
- 頭文件在(子)模塊中包含命名頭文件的內容
保護傘頭文件(Umbrella Header)
- 保護傘頭文件會在其目錄下包含所有頭文件信息
- 使用通配符submodules (module *) 可以為每一個包含的頭文件創(chuàng)建一個子模塊:
- AST/Decl.h?->?ClangAST.Decl?
- AST/Expr.h?->?ClangAST.Expr?
模塊編譯過程:
編輯模塊文件過程:
從頭文件到模塊化
從頭文件編程轉換到使用模塊非常簡單:
庫方面:合并復合定義的結構、函數(shù)、宏,并且為頭文件導入依賴,最后編寫好模塊地圖;
開發(fā)者方面只需要從“#include”過渡到“import”:
當然,你也可以使用工具來自動化重寫代碼,非常簡單。
工具
編輯性能
使用模塊能夠提升語法解析性能:
- 模塊化的頭文件只需要解析一次,之后放在緩存中,于是m×n --> m+n
- 所有基于源(source-based)工具都能帶來好處
- 自動鏈接大大簡化了庫的使用
- 自動導入可以阻止“#include”帶來的可怕的調試結果
調試流
通過DWARF的雙程調試有損耗:
- 只能獲得“用過”類型和函數(shù)
- 丟失了行內函數(shù)、模板
另外調試過程還會出現(xiàn)信息冗余
那使用模塊的調試又會怎樣?
1.提高了構建性能
- 編譯器發(fā)出的DWARF更少
- 鏈接器清除重復的DWARF也更少
2.提高了調試體驗
- 調試器的ASF精度非常完美
- 調試器不需要尋找DWARF
總結
總而言之,C/C++使用模塊化非常有潛力:
- 編譯/構建時間的縮短
- 修復各種預處理問題
- 更好的工具體驗
- 通過設計,能夠平穩(wěn)地過渡
- Clang實現(xiàn)已經在進行了
這個Slide在Hacker News上引起了激烈討論,大部分網友還是贊成模塊化的方式:
baberman:對我來說沒什么不便,而且還給出了過渡方案,可能會很適合某些C/C++項目。我們應該對任何提升C/C++性能的想法持開放態(tài)度。
greggman:預處理有什么不好嗎?如果我不想用預處理,我完全可以使用Objective-C等?,F(xiàn)在的機器性能已經夠強大了,import在編譯上的性能優(yōu)勢對我來說沒有任何吸引力,我更喜歡C/C++的傳統(tǒng)方式。
msbarnett反駁greggman:我認為這正是這份提議的精髓所在,你既可以保留使用#include,也可以從現(xiàn)在開始就轉向import模塊的方式。
_djo_:這個想法會非常有前途!要說缺點的話就是來得太遲了!
nkurz:我不同意“m個頭文件+n個源文件 --> m×n倍編譯性能”。只要使用“#ifndef _HEADER_H”就不會出現(xiàn)這個問題,或者,為什么不使用#include_once <header.h>來解決呢?預處理很可怕嗎?預處理確實有一些問題,但是卻是可以克服的。
SeoxyS:我不關心性能,現(xiàn)在性能已經不是問題了,我更關心怎樣給開發(fā)者更少的負擔。
各位CSDN網友是怎樣看的呢?歡迎一起討論。
相關鏈接:Doug的Slide、Hacker News上的討論
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的为什么应该用模块取代C/C++中的头文件?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国外较好的IT网站
- 下一篇: IOS中的AFNetworking框架的