1. 程式人生 > >c++與java的優缺點!

c++與java的優缺點!

大多數程式設計師都認為C/C++會比Java語言快,甚至於覺得從Java語言誕生以來,“執行速度緩慢”的帽子就應當被扣在頭頂,這種觀點的出現是由於Java剛出現的時候JIT編譯技術還不成熟,主要靠直譯器執行的Java語言確實性能比較低下。但是在今天JIT編譯技術已經發展成熟之後,Java語言有可能在速度上與C/C++爭一日長短了嗎?這個問題的答案,讓我們從兩者的編譯器談起。

在學習C/C++或者想要學習C/C++可以加入我們的學習交流QQ群:788649720,群內有學習資源,大家一起學習交流!

Java與C/C++的編譯器對比實際上是代表了最經典的JIT編譯器與靜態編譯器的對比,也很大程度上決定了Java與C/C++的效能對比的結果,因為無論是C/C++還是Java程式碼,最終編譯之後被機器執行的都是本地機器碼,哪種語言效能更高,除了它們自身的API庫實現得好壞以外,其餘的比較就成了一場“拼編譯器”、“拼輸出程式碼質量”的遊戲。當然,這種比較也是剔除了開發效率的片面對比,語言間孰優孰劣,誰快誰慢的問題都是很難有結果的爭論,下面我們就回到正題,看看這兩種語言的編譯器各有何優勢。

Java虛擬機器的JIT編譯器與C/C++的靜態優化編譯器相比,可能會由於下列這些原因導致輸出的原生代碼有一些劣勢(下面列舉的也包括一些虛擬機器執行子系統的效能劣勢):

首先,因為JIT編譯器執行佔用的是使用者程式執行時間,具有很大的時間壓力,它能提供的優化手段也嚴重受制於編譯成本。如果編譯速度不能達到要求,那使用者將在啟動程式或程式的某部分察覺到重大延遲,這點使得JIT編譯器不敢隨便引入大規模的優化技術,而編譯的時間成本在靜態優化編譯器中並不是主要的關注點。

其次,Java語言是動態的型別安全語言,這意味著需要由虛擬機器來確保程式不會違反語言語義或訪問非結構化記憶體。在實現層面上看,這就意味著虛擬機器必須頻繁進行動態檢查,如物件例項訪問時檢查空指標、陣列元素訪問時檢查上下界範圍、型別轉換時檢查繼承關係等等。對於這類程式程式碼沒有明確寫出的檢查行為,儘管編譯器會努力進行優化,但是總體上仍然要消耗著不少的執行時間。

Java語言中雖然沒有virutal關鍵字,但是使用虛方法的頻率卻遠遠大於C/C++語言,這意味著執行時對方法接收者進行多型選擇的頻率要遠遠大於C/C++語言,也意味著JIT編譯器在進行一些優化,如方法內聯時難度要遠大於C/C++的靜態優化編譯器。

Java語言是可以動態擴充套件的語言,執行時載入新的類可能改變程式型別繼承關係,這使得很多全域性的優化都難以進行,因為編譯器無法看見程式的全貌,許多全域性優化措施都只能以激進優化的方式來完成,編譯器不得不時刻注意並隨著型別變化而在執行是撤消或重新進行一些優化。

在學習C/C++或者想要學習C/C++可以加入我們的學習交流QQ群:788649720,群內有學習資源,大家一起學習交流!

Java語言中的物件記憶體分配都是堆上進行,只有方法中的區域性變數才在棧上分配。而C/C++的物件則有多種記憶體分配方式,既可能在堆上分配,也可能在棧上分配,如果可以把執行緒私有的物件在棧上分配,將可以減輕記憶體回收的壓力,也不需要考慮記憶體屏障方面的問題。另外,C/C++中主要由使用者程式程式碼來回收分配的記憶體,這就不存在無用物件篩選的過程,因此效率上(僅指執行效率,排除了開發效率)也垃圾收集機制要高。

Java語言相對C/C++的劣勢上面說了一大堆,倒不是說Java就真的不如C/C++了,相信大家也注意到了,Java語言的這些效能上的劣勢都是為了換取開發效率上的優勢而付出的代價,動態安全、動態擴充套件、垃圾回收這些“拖後腿”特性都為Java語言的開發效率作出了很大貢獻。何況,也不見得就沒有Java的JIT編譯器能做,而C/C++的靜態優化編譯器不能做的優化:由於C/C++編譯器的靜態性,以執行期效能監控為基礎的優化措施它都無法進行,如呼叫頻率預測(Call Frequency Prediction)、分支頻率預測(Branch Frequency Prediction)、裁剪未被選擇的分支(Untaken Branch Pruning)等,這些都會形成一些Java語言獨有的效能優勢。

在學習C/C++或者想要學習C/C++可以加入我們的學習交流QQ群:788649720,群內有學習資源,大家一起學習交流!