http://c.biancheng.net/view/3871.html
本節我們來介紹一下使用 Qt 編程過程中常用的術語和名字,它們不一定專屬於 Qt,在其它的 C/C++ 開發過程中也會使用到。
Project
Project 的中文翻譯是“項目”或者“工程”,這里的項目是指為實現某個相對獨立功能的程序代碼合集,這些代碼不單單是放在一塊,而是有相互之間的關聯性,並且有專門負責管理該項目的項目文件,比如:
- Qt 使用 .pro 文件管理項目;
- VC++ 則使用 .vcproj 作為項目文件。
集成開發環境通常都是依據項目文件(.pro/.vcproj)管理和構建項目。
Makefile
即生成腳本,雖然可以直接調用編譯器如 g++ 編譯程序,但是如果項目里的代碼文件變多了,哪些代碼文件更新了需要重新編譯,哪些代碼沒有改不需要重新編譯等等,靠程序員自己記憶去處理是比較麻煩的事,還有哪些代碼需要預處理或是鏈接哪些庫文件, 這些都是繁雜的過程。為了規范程序的編譯生成過程,產生了規范化的生成腳本,就是 Makefile,生成器 make 可以依據規范的 Makefile 自動生成目標程序或庫文件。
簡單的說,就是定義好 Makefile ,讓程序員只需要去關注如何編寫代碼,而生成程序過程中的臟活累活都交給 make 程序。
現在 Makefile 通常都有工具自動生成,如 qmake 工具, 這樣就大量減輕了程序員的負擔。
Debug 和 Release
Debug 即調試,Release 即發行。代碼編寫之后,生成的目標程序或庫文件通常不會絕對正確,或多或少有些毛病(bug), 因此需要進行糾錯調試(Debug)。調試過程中需要源代碼和二進制目標程序之間一一對應的關系, 這樣才能定位到錯誤代碼,所以 Debug 版本的程序是臃腫而不進行優化的。
與之相對的是 Release 發行版,在糾正了發覺到的錯誤后,需要發布程序用於實際用途,實際應用時強調運行效率高,減少冗余代碼,因此會對二進制程序進行大量優化,提升性能。這樣發布的二進制目標程序就是 Release 版。
Debug 版本和 Release 版本使用的庫文件不一樣:
- Debug 版本程序通常鏈接的也是 Debug 版本的庫文件,比如 libQt5Guid.a/Qt5Guid.dll,庫文件的簡短名(不含擴展名)都是以 d 結尾的,Debug 庫通常都比較大 。
- Release 版本程序鏈接的通常就是 Release 版本的庫文件,Release 版本庫文件名字比 Debug 版本庫文件少一個字母 d ,如 libQt5Gui.a/Qt5Gui.dll,而且 Release 版本庫一般都比 Debug 版本小很多,運行效率也高很多。
C++11 標准
時代在變化,C++ 標准也在前進。C++ 正式公布標准有 C++98、C++03、C++11。最新的 C++11 標准是2011年8月12日公布的,在公布之前該標准原名為 C++0x 。這是一次較大的修訂和擴充,建議讀者專門學一下。
Qt 從 4.8 版本就開始用 C++11 新特性了。編譯器里面開始支持 C++11 的版本是 MSVC 2010、GCC 4.5、Clang 3.1,這之后版本的編譯器都在逐步完善對 C++11 的支持,現在新版本編譯器對新標准的支持都比較全面了。
Qt 官方在編譯 Qt5 庫的時候都是開啟 C++11 特性的,如果我們要在自己項目代碼啟用新標准,需要在 .pro 文件里面添加一行:
CONFIG += c++11
如果是 Qt4 版本則是添加:
gcc:CXXFLAGS += -std=c++0x
MSVC 編譯器默認開啟 C++11 特性,GCC(g++命令)則需要自己添加選項 -std=c++0x ,上面 CXXFLAGS 就是為 GCC 編譯器(g++命令)添加 -std=c++0x 選項。
Dynamic Link 和 Static Link
Dynamic Link 即動態鏈接,Static Link 即靜態鏈接。
動態鏈接庫
目標程序通常都不是獨立個體,生成程序時都需要鏈接其他的庫,要用到其他庫的代碼。對於多個程序同時運行而言,內存中就可能有同一個庫的多個副本,占用了太多內存而干的活差不多。
為了優化內存運用效率,引入了動態鏈接庫(Dynamic Link Library),或叫共享庫(Shared Object)。使用動態鏈接庫時,內存中只需要一份該庫文件,其他程序要使用該庫文件時,只要鏈接過來就行了。由於動態庫文件外置,鏈接到動態庫的目標程序相對比較小,因為剝離了大量庫代碼,而只需要一些鏈接指針。
使用動態庫,也意味着程序需要鏈接到如 *.dll 或 *.so 文件,得提前裝好動態庫文件,然后目標程序才能正常運行。
靜態鏈接庫
靜態庫就是將鏈接庫的代碼和自己編寫的代碼都編譯鏈接到一塊,鏈接到靜態庫的程序通常比較大,但好處是運行時依賴的庫文件很少,因為目標程序自己內部集成了很多庫代碼。
庫文件后綴
Linux/Unix 系統里靜態庫擴展名一般是 .a,動態庫擴展名一般是 .so 。Windows 系統里 VC 編譯器用的靜態庫擴展名一般是 .lib,動態庫擴展名一般是 .dll 。
MinGW 比較特殊,是將 GNU 工具集和鏈接庫從 Linux/Unix 系統移植到 Windows 里, 有意思的情況就出現了,MinGW 使用的靜態庫擴展名為 .a ,而其動態庫擴展名則為 .dll, .a 僅在生成目標程序過程中使用,.dll 則是在目標程序運行時使用。
Explicit Linking 和 Implicit Linking
Explicit Linking 即顯式鏈接,Implicit Linking 即隱式鏈接,這兩種都是動態鏈接庫的使用方式。
動態鏈接庫通常都有其導出函數列表, 告知其他可執行程序可以使用它的哪些函數。可執行程序使用這些導出函數有兩種方式:一是在運行時使用主動加載動態庫的函數,Linux 里比如用 dlopen 函數打開並加載動態庫,Windows 里一般用 LoadLibrary 打開並加載動態庫,只有當程序代碼執行到這些函數時,其參數里的動態庫才會被加載,這就是顯式鏈接。顯式鏈接方式是在運行時加載動態庫,其程序啟動時並不檢查這些動態庫是否存在。
隱式鏈接是最為常見的,所有的編譯環境默認都是采用隱式鏈接的方式使用動態庫。隱式鏈接會在鏈接生成可執行程序時就確立依賴關系,在該程序啟動時,操作系統自動會檢查它依賴的動態庫,並一一加載到該程序的內存空間,程序員就不需要操心什么時候加載動態庫了。比如 VC 編譯環境,鏈接時使用動態庫對應的 .lib 文件(包含動態庫的導出函數聲明,但沒有實際功能代碼),在 .exe 程序運行前系統會檢查依賴的 .dll,如果找不到某個動態庫就會出現類似下圖對話框:

MinGW 是將動態庫的導出函數聲明放在了 .a 文件里,程序運行依賴的動態庫也是 .dll 。
請注意,VC 鏈接器使用的 .lib 文件分兩類,一種是完整的靜態庫,體積比較大,另一種是動態庫的導出聲明,體積比較小。MinGW 鏈接器使用的 .a 文件也是類似的,Qt 官方庫都是按照動態庫發布的,靜態庫只有自己編譯才會有。