每日一發小視頻
剛好最近在學習C++,以前又有其它語言的編程經驗,所以對此剛好有一定發言權。
C++是所有主流編程語言中最難掌握的語言!這一點基本上得到了公認。“主流”一詞不能少,大致可以認為是各類計算機語言排行榜中前50名了那些。有些搞怪的,用來“玩”的語言可能比C++還難,但是它們不主流,也幾乎沒有誰真正用在生產環境,所以沒有必要討論。還有少數人認為最難的主流編程語言是彙編或LISP。這也是有道理的。不過不管怎麼說,說C++的難度處於主流語言中前三位,就更加無懈可擊,誰也否定不了。
我們這裡討論難度,主要都是以純語言和核心標準庫函數來說的,沒有包含衍生的整個生態系統。比方說說JavaScript的難度那就是純JavaScript,而沒有包含jquery、vue、node.js等。再比如討論JAVA難度,同樣不包含安卓開發、spring甚至hadoop。再比如Python就不包含numpy、django甚至人工智能。
就我接觸過的一些編程語言,JAVA、C#、Python、PHP、JavaScript、Go、C、R、scala、F#,它們在純語法上,和C++的難度完全不在一個重量級!一種小巫見大巫的感覺。我剛加入一個C++團隊,凡是接觸過其他語言的,都說C++太難了。而有部分成員說C++簡單的,一看都是剛畢業沒有幾年,只玩過C++而不知道其他語言的(一種初生牛犢的感覺吧)。
說了這麼多廢話,下面開始討論為什麼C++難,難在哪裡。寫的比較隨意,想到哪裡寫到哪裡。
第一、C++直接編譯成本地代碼
本地代碼,就是直接可以在操作系統上運行的,不需要藉助其他進程去引導它。C#、JAVA是運行於虛擬機的,Python、JavaScript是需要解釋器的。也就是這些語言離開了虛擬機或解釋器就運行不起來。但也正因為如此,它們才變得相對簡單。因為虛擬機和解釋器屏蔽了底層的很多細節。比方說你用JAVA寫一段代碼,你甚至都不需要知道到底操作系統是Windows還是Linux,你眼中的內存也僅僅是虛擬機上(簡化的)內存。而C++不得不考慮底層的很多細節,導致很難。同樣需要考慮底層的還有C、Go、rust等。單從這個角度看,這類編程語言是同一難度級別的。
第二、C++沒有完善的自動垃圾回收機制
當我們一提到C/C++,大概首先想到的就是它們的指針。指針是C/C++的精髓,同樣也是難度的根源之一。JAVA、Python等很多編程語言都是沒有指針的。因為它們的虛擬機或解釋器自帶自動垃圾回收。指針實際上就是內存地址。當我們新建一個對象時,必須向操作系統分配內存(內存地址、指針),而對象使用完畢後,又應當回收。最常見的問題就是忘了回收或者其他變量正在引用就提前回收了。比如一個函數申請了內存,到底是該函數負責回收還是調用方負責回收?而帶垃圾回收的語言,編程者完全不用操心這些事,完全不需要知道內存是如何分配的,該誰來回收以及如何回收。自動垃圾回收有利有弊,利是對開發者簡單,弊是運行效率相對低下。C/C++是注重運行效率而犧牲了簡單性。
第三、C++使用大量的預編譯
在沒有預編譯的語言中,採用if else以及函數來完成類似的功能。比如if 32位操作系統該怎麼做else怎麼做。但是這樣的代碼最後是會運行的。而預編譯時,假如不是32位操作系統(編譯階段就已經知道),相應的代碼不會編譯,這樣就降低代碼大小,且少了一個if else判斷,效率更高。而預編譯中的宏則是直接替代,防止了函數調用。函數調用也是需要損失性能的。正是這種過分強調性能,導致預編譯被大量使用,給代碼閱讀和調試帶來極大的不方便。
第四、C++歷史包袱太多
C++是上世紀80年代的發明,還是比較古老了。在長期的發展中,存在大量的歷史問題。比方說,一個字符串處理,就千奇八怪,它甚至都沒有字符串類型這一說法。STL裡有std:string,但也不是唯一的或做多的選擇。相反,在其他所有現代語言中,字符串如何處理,都有幾乎唯一的選擇。C++選擇太多,一方面你必須面臨如何選擇的問題,另一方面為了看懂別人的代碼,你還不得不學習其他的選擇是如何做的。歷史包袱,就是說為了兼容以前的代碼和以前的規範,不得不使整個系統非常複雜龐大。我們就說說Python吧,大家都知道目前有一個問題就是Python2.x和3.x的問題。你看,Python就果斷地拋棄了2.x這個包袱(新版不再完全兼容老版),否則也會越來越複雜。C++沒有這麼做,因為老系統太多了,而且用的人多,根深蒂固,基本不可能推翻重來。像Go、D、rust這些新興語言想取代年老的C++,都一直沒有成功。如果C++想甩掉歷史包袱(變成一門新的語言),那和rust、Go等又有什麼區別?
第五、C++沒有一個唯一的大東家
我們知道很多語言背後都有一個團隊在運營,它們有絕對的權力或者說叫話語權,比如微軟的C#、甲骨文的JAVA、谷歌的Go。Python(準確地說是cPython),也有唯一的開源項目,統一行動。再看C++,它不隸屬於任何一個團隊,它沒有唯一的編譯器開發商。微軟的msvc,Linux的g++,還有clang等等。這麼多廠商,誰也不佔主導地位,誰也不聽誰的。最後只能成立一個C++標準協會,大家協商著來,相互妥協。這種相互妥協,導致C++變得異常複雜,既兼容這個又兼容那個,甚至可以說是個“怪胎”。
第六、C++編譯器太多,風格不一致
這個其實是上一條的延續(篇幅太長)。剛說了C++沒有哪個廠家一家獨大,靠標準協會協調。C++標準異常複雜。甚至有個詞語叫做“未定義行為”。同樣的代碼,在這個編譯器可以運行,在另一個編譯器不行或者結果不一樣,這種情況太多了。迄今為止沒有一個公認的嚴格的C++規範,C++是非常自由的。自由就意味著難度大。Python為什麼簡單,就是因為它不自由,連變量名如何寫,代碼縮進都中規中矩。風格一致。不過也有其他語言和C++相似,比如JavaScript,它也是多廠家,標準不統一,風格不一致。
第七、C++語法博大精深
上面說了那麼多,強調的都是背後的原因,那具體說來,到底C++難在哪裡呢?這個不好說,下邊只是我的理解,簡單羅列出來。複雜的const和static語義。指針運算,取地址運算,引用,比如*、&、&&。模板與泛型。函數式編程。構造函數、拷貝構造函數、賦值構造函數、移動構造函數、析構函數。多重繼承。
第八、第三方庫不多
相對說來,C++主張從輪子造起,第三方庫不是太多。很多看似簡單的功能都得自己實現或者拼命地找庫。一般說來,C++使用時間長了,就掌握得更好,所謂越老越吃香。因為可以不斷積累庫函數。而類似JAVA、Python這種,一方面標準庫就自帶,另一方面,遇到問題,網上一搜索,拿來就用。像線程、XML、json、sqlite3、TCP、http訪問、crc32/md5,像這些如此基礎的功能都沒有提供自帶標準函數。
犍為真人
C++是在C語言基礎上發展而來的,學過C語言的程序員再來學習C++會更會入手,當然C語言也不是很好學,更何況C++要比C語言難一點。
第一從語法來說,C++編程語言還是比較簡單,只要掌握C++編程方式與常見的java,PHP都很相識。
第二是拋異常,C++不像其他編程語言簡單的打印就可以看出錯誤地方,C++需要編譯出來在運行,但是編譯過程很難發現有錯誤信息。
第三C++沒有標準類庫,不像python到處都是免費的類庫可以直接使用。
第四語言設計上的複製性,主要體現在繼承、封裝、多態等等。
雖然C++是比計較難學的一種編程語言,但是它的市場很大,大型遊戲開發,科技算法,網絡軟件開發,操作系統等領域。
常青春科技
個人感覺國內多數人混淆了兩個概念:編程語言的語法知識和編程能力。多數人剛學習時,重心花在龐大、全面的語法細節中,結果如在大海中劃個小船一樣,最終迷失了方向而放棄。但在實際編程過程中,多數時間使用到的語法很少。
因此,真正想進入編程行業,培養編程能力更重要。只要編程能力上來了,再掌握編程語法要容易得多。
編程能力體現在C語言上,就是解決問題的流程細節中,簡單說就是會畫解決問題的流程圖。而對於C++語言,主要是系統構架上,體現在掌握類之間的關係、對象之間的關係。
教人會點語法容易,因此高校與培訓機構多偏於這方面。但培養人的思維與觀念,太難了,誰會去做啊!