程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 冒號課堂§6.1:系統語言

冒號課堂§6.1:系統語言

編輯:關於JAVA

第六課 語言簡評(1)

課前導讀

本課對一些主流語言進行了簡單的比較和評價。一家之言,權作助興。

本課共分四節——

系統語言——權力的雙刃劍

平台語言——先搭台後唱戲

前台語言——視覺與交互的藝術

後台腳本——敏捷開發的利器

6.1系統語言——權力的雙刃劍

居高者形逸而神勞,處下者形勞而神逸        —《洪應明·菜根譚》

關鍵詞:C族語言,C語言,C++,D語言

摘要:簡談C、C++和D

!預覽

·通禅悟道者拈花不語,坐井觀天者蛙鳴鼓噪

·Java程序員大多被慣壞了,環保意識要淡薄得多

·(指針)用得好可以是削鐵如泥的神兵利器,用得不好則可能是自我毀滅的罪惡淵薮

·OOP又不是金子,含量越高越好。試圖把一切都裝進OOP的箱子裡的想法無異於削足適履

·它們(系統語言)的理念是:優化機器的時間而不是人的時間,優化機器的記憶而不是人的記憶;假設編譯器是愚蠢的而程序員是聰明的,因此賦予程序員更多的權利、義務與責任

·C++是匹無辔無鞍的野馬,看似桀骜不馴,若能順性而御,必能足踏飛燕,行千裡而不勞

?提問

為什麼C++不支持自動垃圾回收?

在C++中如何解決內存釋放問題?

系統語言有哪些特點?

在不引入OOP的前提下,C語言可以借鑒C++的哪些特征?

D語言比C++有哪些改進?

在電腦性能日益提升的今天,還有必要在乎程序的性能和效率嗎?

:講解

教室裡,學員們正熱火朝天地討論著流行的編程語言。冒號推門而入,仿佛沸水鍋裡被澆了一瓢冷水,立刻平靜下來。

冒號笑吟吟地看著大家:“怎麼不討論了?”

眾人齊道:“該您了!”

“首先需要聲明的是,本課評論編程語言,乃是應眾位之邀,實非本意。”冒號變得嚴肅起來,“因為這種評論,不可避免地會帶上個人色彩,容易產生誤導。有道是,通禅悟道者拈花不語,坐井觀天者蛙鳴鼓噪。”

眾人迅速自動對號:看來我們就是一群蛤蟆。

“這樣一來,我的處境就很尴尬了。”冒號自嘲著。

有人在幸災樂禍地偷笑。

“也罷,即使作蛙鳴,至少也要先跳出井來。”冒號毅然決然地加入了蛤蟆的行列,“要談,就旗幟鮮明地談,該贊歎的就贊歎,該鄙視的就鄙視。說些你好我好大家好之類不痛不癢的話,倒不如不說。”

歎號一拍大腿:“好,這樣才夠痛快!”

問號忍不住問:“您究竟打算比較哪些主流語言呢?”

冒號回答:“就談談第一堂課提到的最流行的十二種語言吧。按語法特征可將它們分為三類:C族靜態語言五種——C、C++、Java、C#和D;非C族靜態語言兩種——VB和Delphi;動態語言五種——Perl、PHP、Python、Ruby 和JavaScript 。”

歎號表示懷疑:“這麼多種語言怎麼比較得過來?”

冒號解釋:“我們主要比較第一類的C族語言,這些也是今後學習的重點,其他的只是泛泛而談。”

引號猜測:“因為他們更重要?”

“可以這麼說。”冒號直截了當,“毋庸諱言,在當今的主流語言中,C族語言應用范圍之廣、使用人數之多、影響力之巨都是其他類語言所無法比擬的。它們之間的關系從名字上就能看出:C語言的前身是B語言;其後是C++;Java曾被稱為C++++--,意思是在C++上增點東西再減點東西;C#中#就是四個疊起的加號[1];最後D語言干脆在字母上進行升級。”

句號推斷:“B語言、C語言、D語言,下一個該D++、D#或E語言了。”

誰知冒號卻說:“E語言已經有了,與Java的語法很像。甚至F語言也有了,但不是C族語言,而是Fortran族的。這不,微軟還在.Net平台上推出了F#語言,不過這裡的F指的是‘Functional’,即函數式。”

逗號向往著:“不如直接搞個終極的Z語言,成為全世界程序員的唯一指定語言,多省事!”

“這難度不亞於全人類共用一種語言。”冒號笑道,“願望是美好的,我們還得面對現實。不扯遠了,你們先談談一下這些C族語言各自的特點吧。”

眾人心想:老冒怎麼跟國足一個毛病,老喜歡回傳,就是不直接射門,真是急煞人也!

問號揀了個軟柿子:“C語言是C族老大,又是唯一的純過程式語言,當然與眾不同啦。”

引號一板一眼:“C++在過程式的基礎上又引入對象式和泛型式,同時保持了C的高效性和底層開發能力。”

逗號接道:“Java既繼承了C++的優點,又克服了C++的復雜性,雖然底層開發能力有所減弱,但具備平台無關性。”

句號不緊不慢:“C#兼具C++與Java各自的優點,但效率上不如C++,跨平台方面不如Java。”

歎號後悔嘴慢:“剩下一個最陌生的D語言,在第一堂課之前還真沒聽說過,怎麼擠上主流語言位置的?我想。。。呃,它總該比C++要高級吧。”

冒號評價:“各位談得雖然簡單了些,也算八九不離十吧。下面我稍微展開些來講。”

此時眾人有一個共同的願望,希望老冒這次能痛快地單刀赴會、直搗黃龍。

冒號似乎看出大家的心思,開始口若懸河:“關於C語言,前面多次提到。這是一把歷久彌新的寶劍,一旦出鞘,依舊寒光逼人,鋒利無俦。有了它,便如戰將有了佩劍,平添一分獨闖敵營的膽氣。盡管以現代的眼光來看,它存在不少缺點,但即使拋開C語言輝煌的歷史不談,單就其以如此高齡在諸多後輩沖擊之下仍屹立不倒而論,讓人無法對其多加苛求。”

逗號提出異議:“但語言不是讓人崇拜的,而是讓人運用的。一門語言無論過去如何榮光,如果不適應現代發展趨勢,還是可能被淘汰。”

“說得非常好!”冒號竟然鼓起掌來,“迄今為止本課堂對於具體知識的講授不算太多,但一直提倡獨立思考,不要盲從權威。如果你們能做到這一點,本班的目標也就實現了一半。回頭再說說C語言,它源自Unix操作系統的開發,以其良好的抽象性和可移植性取代了匯編語言作為系統開發語言。因其簡潔實用、靈活高效,很快從系統領域發展到其他領域而成為通用語言。隨著新興語言的崛起以及硬件性能的大幅提高,C語言的缺點也日益顯著:過於寬松的類型檢查、容易出錯的內存管理、相對貧乏的語言特征等等。雖然自身還在發展,它的市場份額日益減少乃是不爭的事實。但在相當長的時間內,它在其所擅長的領域裡仍會占舉足輕重的一席之地。如果C能借鑒C++的 命名空間、重載、異常處理和STL等非OOP的特征,它的生命力絕不會比任何OOP語言弱。附帶說一句,C雖然沒有直接支持OOP的語法,但經過適當的設計還是能實現OOP的[2]。”

引號咨詢道:“關於C語言的學習,您有何建議?”

“精讀K&R的《The C Programming Language》,此書不過二百頁,堪稱C語言的劍訣。其中的R即Dennis Ritchie,是C的創造者,同時也是Unix的締造者之一,是真正的大師。如今的大師,同博士、教授、院士等頭銜一樣,嚴重地通貨膨脹了。”冒號不無感慨。

問號尖銳地問:“C++既保持了C的底層開發能力,又引入了OOP,C的處境想必更加艱難吧?”

冒號坦承:“這是不假。C++成功的一個重要因素是對C語言的兼容,由此吸引了大批的C程序員。但這不是沒有代價的,C++在兼容C的同時也保留了C的許多缺陷。Java成功的地方有很多,一個不容忽視的因素是它徹底擺脫了與C兼容的桎梏。由於C++對C的改革不徹底,又過於龐雜,並且效率上不如C,這使得C仍有其生存空間。略有諷刺意味的是,對C++批判最激烈的往往來自C的社區,比如Linux之父Linus Torvalds就曾激烈地批判過C++。”

“Linus?那可是我的偶像呢!”歎號驚訝道。

冒號勸誡:“如果你因為是他的粉絲而後悔學C++,那就是為他人的偏執買單,不管那人名氣有多大。”

句號指出:“C++最為人诟病的地方有:語法過於復雜,學習曲線陡、開發效率低;支持的范式過多;OOP不徹底;自省(reflection)功能不足;支持指針操作導致安全隱患;沒有自動垃圾回收,容易內存洩漏;沒有線程支持;沒有豐富的標准庫支持圖形界面、網絡編程等。”

“罪狀不少哇!這些說法都有一定道理,但有些也有失公允。且聽我一一道來。”冒號當起了辯護律師,“C++比較復雜這點沒錯,Stroustrup說過一句耐人尋味的話: 一種語言不夠復雜是因為它還不夠成熟。成人肯定比兒童復雜,因為他要承擔更大的責任。大家不妨看看Java從1.0到即將的7.0、C#從1.0到即將的4.0的發展過程,是否應證了這一點?當然C++的復雜度的確高於其他語言,但如果不執著於奇技淫巧,它絕非高不可攀。C++的開發效率相比Java與C#,差距主要在兩個方面:一是標准庫不夠完善,二是需要手工回收垃圾。關於前者,的確是C++的一大軟肋,標准庫竟然連企業應用中最常用的圖形界面、網絡編程、數據庫處理、多線程等都不能涵蓋,嚴重障礙了生產力。其實C++也有苦衷,不像Java和C#那樣有大公司的鼎力支持,只靠效率極為低下的標准委員會來維護。98年的一個標准直到03年還在修訂,下一個標准至少要到09年。連Stroustrup都在哭窮,聲稱沒有足夠的人力和時間來開發標准庫,可為何廣受贊譽的Boost庫至今仍徘徊在標准門外?考慮到Boost的創辦人大多出自標准委員會,其他無此背景的類庫恐怕更難登C++之大堂了。相比之下D語言更慘,雖然天生麗質,苦無豪門青睐,只好一直待字閨中。”

歎號感慨:“金錢才是技術的最大推動力啊!”

“話糙理不糙。”冒號也很無奈,“再來談談有關自動垃圾回收的問題。在C++中,程序員也不是非得手工清理垃圾不可的。更好的辦法是遵循RAII的慣用法(idiom)[3],通過智能指針(smart pointer)來解決內存釋放問題。”

逗號聽不明白:“什麼是RAII?”

“RAII是Resource Acquisition Is Initialization的縮寫,直譯為‘資源獲取即初始化’。”冒號解釋,“其實更准確的叫法應該是RRIF(Resource Release Is Finalization),即‘資源釋放即終結化’[4]。其思想是:將資源的取放與某一對象的生命周期綁定,初始化對象時獲取資源,終結化對象時釋放資源。用戶代碼不再直接管理資源,只需控制相應的對象即可。這樣代碼得以簡化,資源的有效性也得以保障,並且還是異常安全的(exception-safe)[5]。”

問號猜想:“在Java中沒有這種用法,是因為它已經有了垃圾回收器嗎?”

冒號搖搖頭:“問題的關鍵不在這裡。資源不只限於內存,還包括文件、線程鎖、數據庫連接等等,這些都不是垃圾回收器所能解決的。看看Java的數據庫應用代碼吧,對於那些頻繁出現的被try/catch/finally包裹的resultset.close()、statement.close()、connection.close(),你是習以為常呢,還是不勝其煩?”

逗號眼睛一亮:“如果采用RAII的技巧,這些都可以省去了嗎?”

冒號再次搖頭:“可惜Java不像C++或D那樣,能在棧(stack)上創建對象。棧對象有一個的特點,一旦超出其作用范圍,便自動釋放內存。在此之前會調用析構函數(destructor),後者繼而調用釋放資源的代碼。”

幾聲歎息清晰可聞。

冒號續道:“另一方面,盡管自動垃圾回收機制逐漸為大眾所接受——據說C++0x也將部分地支持它——但這種機制也存在缺陷。比如一個Java程序如果在某一時段極耗內存,由於自動垃圾回收的不定時性,不能保證及時清理內存,可能會拋出OutOfMemoryError的錯誤。對於內存有限的系統或實時系統來說,這絕對是一個致命的軟肋。C++不支持自動垃圾回收,正是基於這些方面的考慮。Stroustrup非常顧慮自動垃圾回收帶來的時間和空間上的過多開銷,並且擔心它會影響C++完成其所肩負的底層任務。另外,千萬不要以為有了自動垃圾回收機制就一勞永逸、萬事大吉了。Java程序一樣會有內存洩漏,其幾率甚至可能比C++的更大,因為C++程序員對此更有戒心,而Java程序員大多被慣壞了,環保意識要淡薄得多。”

問號直奔要害:“您如何看待C與C++中的指針?”

冒號欣然接招:“指針是C與C++最大的特色,其他語言要麼不支持,要麼支持得有限。C與C++可以說是成也指針,敗也指針。用得好可以是削鐵如泥的神兵利器,用得不好則可能是自我毀滅的罪惡淵薮。但由於二者定位於系統語言,而指針對於底層操作是必不可少的。同樣道理,二者的數據類型的轉換比其他靜態類型語言更自由,也是源出於此。”

句號總結:“能力越大,責任越大,風險越大。”

“正是此意!”冒號重重地敲了一下桌子,“此話既適用於編程語言,也適用於程序員。至於C++缺少對自省功能的支持,也是因為追求效率,不願在元數據上花時間和空間。說到C++支持的范式過多,程序員過於自由,代碼不標准難維護,這就如同埋怨餐館提供的菜式過多以致難以擺出一桌酒席一樣可笑。最後,指責C++不是100%OOP的說法更是荒謬之極。OOP又不是金子,含量越高越好。試圖把一切都裝進OOP的箱子裡的想法無異於削足適履。典型的如Java中的Math類,邏輯上壓根兒就不存在什麼Math對象,清一色的static方法和常量就是最好的諷刺。在C++中只要在math的namespace中定義一些自由函數就可以了,自然而簡潔。作為一個佐證,Java於J2SE5.0引進了靜態導入(static import)機制[6],不僅在形式上簡化了調用代碼,也在思維上容忍了非OOP的過程式。”

引號發覺:“您好像把對C++所有的責難都化解了。”

“可恨之人必有可憐之處嘛。”冒號俗語反用,“其實C++仍有不少亟待改進之處,D語言就是很好的啟示。D語言的提供了可控制的垃圾回收器;支持線程同步;支持動態數組(dynamic array);支持嵌套函數(nested function);支持契約式設計(design by contract);廢除了C與C++ 中令人頭痛的頭文件(header file)等等。這些都是C++程序員夢寐以求的特征。”

逗號很奇怪:“為什麼D語言名氣這麼小?”

句號吟道:“千裡馬常有,而伯樂不常有,大腕伯樂更稀有。”

眾樂。

冒號拔高了調門:“既然系統語言主要為底層系統的開發服務,這就決定了它們的理念是:優化機器的時間而不是人的時間,優化機器的記憶而不是人的記憶;假設編譯器是愚蠢的而程序員是聰明的,因此賦予程序員更多的權利、義務與責任。無視這種背景和理念而去與其他語言相較,完全是不著筋節,不值一哂。當然這並不排斥系統語言用於應用開發,尤其是C++和D語言。需要強調的是,常見的‘C/C++’的說法很不科學。C與C++雖有千絲萬縷的聯系,但一個簡單,一個復雜;一個純過程式,一個集過程式、對象式、泛型式和元編程於一體。貌合神離,不宜混為一談。”

歎號一個問題憋了半天,不吐不快:“我有一個問題:如今電腦性能這麼高,C與C++如此強調程序的性能和效率還有必要嗎?”

“絕對有必要!”冒號斬釘截鐵,“其一、縱向看,用戶的耐心與電腦的性能成反比,早年一個386人們就滿足了,如今卻忍受不了586;以前16M內存就不錯了,現在1G都嫌小。其二、橫向比,占用資源過多、運行相對緩慢的軟件競爭力也低。其三、在一些應用領域如人工智能、大型計算等方面,普通電腦的性能還遠遠不能滿足要求,超級計算機的存在就是明證。其四、仍有些程序跑在資源有限的主機上,比如嵌入式系統。”

引號再次要求:“能推薦一些C++方面的書嗎?”

冒號直言相告:“學好C一本書足矣,學好C++即使推薦十本仍有遺珠之憾。可以說C++是苦了編程者,甜了著書人。開個小書單:初級——《C++ Primer》和《Thinking in C++》;中級——《The C++ Programming Language》和《Effective C++》系列;高級——《The C++ In-Depth》系列。這裡還要特別推薦一下《The Design and Evolution of C++》,從中你可以看到 C++的設計和演變的來龍去脈,極具啟發性。其他的C++精品書籍還有不少,恕不一一列舉了。C++是匹無辔無鞍的野馬,看似桀骜不馴,若能順性而御,必能足踏飛燕,行千裡而不勞。”

,插語

[1] 更官方的說法是“#”來自音樂中的高半音符號。

[2] 比如文獻【4】設計了一種用C來實現OOP的機制。

[3] RAII是由Bjarne Stroustrup首先提出的,參見文獻【2】。

[4] 說它更准確,是因為資源獲取的代碼不一定需要出現在constructor中,但資源釋放的代碼一定出現在destructor中。

[5] 指即使發生異常(exception)也不會導致資源洩露。

[6] 比如,在靜態導入Math類(import static java.lang.Math.*;)後,代碼中可以直接調用sqrt、log、max等數學方法,不再需要“Math.”的前綴了。

。總結

·C++對C語言的兼容是其成功的一個重要因素,但同時也繼承了C的一些缺陷。

·C++設計者沒有直接支持自動垃圾回收,是擔心它造成過大的時空開銷,同時會削弱底層開發能力。

·除了手工釋放內存外,C++提倡運用RAII原則解決包括內存在內的資源管理問題。

·C與C++對指針的全面支持和寬松的類型轉換限制,均出於底層系統開發的需要。

·C可以借鑒C++的命名空間、重載、異常處理和STL等非OOP的特征。

·D語言提供了可控制的垃圾回收器,支持線程同步、動態數組、嵌套函數和契約式設計,並廢除了頭文件和前置聲明(forward declaration)。

·在程序性能與生產效率之間,系統語言更看重前者,它們在賦予程序員更多的權利的同時,也帶給程序員更多的負擔。

·程序的性能和效率永遠是重要的。一方面,用戶對軟件性能的期望越來越高;另一方面,有時硬件性能與軟件需求並不匹配:有些應用(如人工智能、大型計算)對程序的性能和效率要求極高,有些系統(如嵌入式系統)的資源十分有限。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved