采訪 | Tim Anderson
整理 | 云昭
出品 | 51CTO技術(shù)棧(微信號(hào):blog51cto)
上周,5月6-7日,于慕尼黑舉行的Qt World Summit大會(huì)上,C++之父Bjarne Stroustrup在其《21世紀(jì)的C++》主題演講前特別接受了外媒DevClass的專訪,訪談中涉及到很多,比如:
如何寫出現(xiàn)代風(fēng)格的C++?為什么替代這門語言很難?AI潛在的風(fēng)險(xiǎn),以及為何擁有多套略有差異的編譯器反而是一件好事?等等。
盡管演講題目如此,Stroustrup并未將重點(diǎn)放在C++26(下一個(gè)主要版本)即將到來的特性上,比如反射和契約(contracts)。
圖片
他說:“這門語言并不只是最近新加進(jìn)去的功能而已。要寫出符合當(dāng)代的C++,你得把從語言誕生早期到現(xiàn)代的各種特性組合起來使用……我最主要想說的并不是‘有幾個(gè)特別棒的新特性你一定要用’,而是‘你應(yīng)該用好現(xiàn)在這門語言本來的樣子’。它現(xiàn)在是一個(gè)更加連貫的整體,更高效、更具表現(xiàn)力、更安全?!?/span>
C++程序員應(yīng)該用哪些特性,才能寫出‘現(xiàn)代風(fēng)格’的代碼?
Stroustrup說:“很多關(guān)鍵點(diǎn)在于這些特性是如何相互配合的。我一直在努力讓程序員能用語言本身更直接地表達(dá)意圖。比如寫循環(huán),現(xiàn)在95%到99%的循環(huán)場(chǎng)景其實(shí)都是‘對(duì)這個(gè)容器里的所有元素做點(diǎn)什么’,根本不用手動(dòng)定義循環(huán)變量。你可以寫成‘for x in y’或類似的結(jié)構(gòu),直接表達(dá)你要做的事情。這樣編譯器更容易優(yōu)化,程序員犯錯(cuò)的概率也更低,代碼也更簡(jiǎn)潔。”
他還提到范型編程:“類型通常是可以自動(dòng)推導(dǎo)出來的,所以你總能得到正確的類型?!?/span>
另一個(gè)至關(guān)重要的點(diǎn)是資源管理。他說:“如果你用RTTI(運(yùn)行時(shí)類型識(shí)別)來確保資源被正確釋放,比如對(duì)象被銷毀、文件被關(guān)閉等等,你需要有作用域來承載這些資源。所以,所有資源都應(yīng)該由一個(gè)句柄(handle)來管理,句柄本身存在于作用域內(nèi)。這樣,絕大多數(shù)內(nèi)存泄漏問題就不見了。”
現(xiàn)代C++開發(fā)者有哪些做法是千萬不能做的?
“千萬不要把裸指針當(dāng)作資源句柄來用?!彼f,“如果這么做,就完全違背了我剛剛說的原則。也絕不要用單個(gè)裸指針去傳遞一組元素,比如指針指向數(shù)組。你根本不知道數(shù)組里有多少個(gè)元素,也無法做合理的范圍檢查。但如果你傳遞的是vector,它自己就知道自己有多少元素、是什么類型?!?/span>
“另外,我?guī)缀踉僖膊挥脧?qiáng)制類型轉(zhuǎn)換(cast)了。范型編程的好處就在這里。不用類型轉(zhuǎn)換,類型錯(cuò)誤的風(fēng)險(xiǎn)就大大降低?!?/span>
“以前要從函數(shù)里返回一大堆數(shù)據(jù),通常做法是放到動(dòng)態(tài)內(nèi)存里,再把指針返回,然后還得記得手動(dòng)delete?,F(xiàn)在,直接把一個(gè)vector move出來就行,基本是零開銷?!?/span>
在演講中,Stroustrup還強(qiáng)調(diào)了模塊(modules)。用import語句來代替?zhèn)鹘y(tǒng)的#include。因?yàn)?include是傳遞性的,順序會(huì)影響編譯結(jié)果,而且會(huì)導(dǎo)致重復(fù)編譯和一些隱晦的bug。而import沒有傳遞性,編譯也能一次性完成,大大提高效率。
他特別提到的其他特性還包括模板(templates)和概念(concepts)(C++20強(qiáng)制支持的標(biāo)準(zhǔn)特性)。他PPT上的一句話是:“用概念其實(shí)比不用更簡(jiǎn)單?!彼f,自己的生產(chǎn)環(huán)境代碼也沒有用什么比本次演講里更復(fù)雜的特性,而且基本測(cè)試通過之后,已經(jīng)很多年沒有再遇到過資源泄漏。
如何強(qiáng)制團(tuán)隊(duì)寫出符合現(xiàn)代C++風(fēng)格的代碼呢?
Stroustrup承認(rèn)這是個(gè)難題:“在大型代碼庫(kù)里,光靠手冊(cè)式的編碼規(guī)范根本行不通。我們需要工具支持。所以我正在做一套‘profiles’,可以根據(jù)設(shè)定好的規(guī)范來強(qiáng)制檢查。”
不過他也直言,這個(gè)機(jī)制目前還沒有被C++標(biāo)準(zhǔn)采納,短期內(nèi)也不太可能:“很遺憾,標(biāo)準(zhǔn)委員會(huì)這件事上有點(diǎn)迷糊,沒能保證C++26里會(huì)加入?!?/span>
現(xiàn)在開發(fā)者可以用Clang-Tidy之類的工具來輔助檢查?!八呀?jīng)實(shí)現(xiàn)了我稱之為‘C++核心指南(C++ Core Guidelines)’的一部分檢查功能,這是我跟Red Hat、微軟等公司聯(lián)合做的項(xiàng)目?!?/span>
他是否擔(dān)心AI對(duì)C++開發(fā)的影響?
“是的,我確實(shí)很擔(dān)心。不是說AI沒用,但它往往會(huì)把大家引導(dǎo)到以前人們常用但其實(shí)不好的做法上。更糟糕的是,我擔(dān)心人們會(huì)因此失去主動(dòng)發(fā)現(xiàn)問題的能力,因?yàn)榇蠹叶剂?xí)慣于讓AI幫你搞定?!?/span>
像谷歌Carbon這樣的新語言,會(huì)取代C++嗎?
他說:“如果你只針對(duì)一個(gè)小場(chǎng)景,要做出比C++更好的語言其實(shí)很容易。但C++的優(yōu)勢(shì)就在于它能同時(shí)適用于非常多樣化的領(lǐng)域。再說了,就算這些語言成功了,它們也必須跟C++、Python這些語言互操作。如果我們不小心,最后可能不是一個(gè)‘過于龐大的C++’,而是‘十個(gè)都不完整、還互相勉強(qiáng)兼容的小語言’?!?/span>
C++演進(jìn)是不是太慢了?
“你判斷是不是節(jié)奏合適的方法就是,看是不是有一半人覺得太慢,一半人又說太快?!盨troustrup笑說,“是的,我確實(shí)希望比標(biāo)準(zhǔn)委員會(huì)稍微快點(diǎn)。但標(biāo)準(zhǔn)委員會(huì)太龐大了,大家關(guān)注的點(diǎn)太多,這會(huì)拖慢節(jié)奏……不過,我估計(jì)更多C++程序員其實(shí)是覺得‘太快了’。”
不同C++編譯器實(shí)現(xiàn)標(biāo)準(zhǔn)的細(xì)節(jié)差異,會(huì)不會(huì)給開發(fā)者帶來麻煩?
“是的,但你要知道,每個(gè)主流編譯器,甚至每個(gè)非主流的嵌入式編譯器,用戶數(shù)量可能都比大多數(shù)語言多。而且,我很討厭‘單一生態(tài)(monoculture)’。如果歷史告訴我們什么,那就是一旦出現(xiàn)單一生態(tài),一個(gè)bug或一個(gè)毒點(diǎn),整個(gè)生態(tài)就完了。”
他說,雖然主流C++編譯器彼此實(shí)現(xiàn)不完全一致,但它們彼此之間差距其實(shí)已經(jīng)越來越小了?!叭绻挥幸粋€(gè)實(shí)現(xiàn),當(dāng)然有些好處,但那就是單一生態(tài)。而多個(gè)實(shí)現(xiàn)就能帶來競(jìng)爭(zhēng)空間,也有利于創(chuàng)新。它們不可能完全一致——事實(shí)上,至今沒有任何一個(gè)C編譯器是100%標(biāo)準(zhǔn)兼容的,從來沒有過?!?/span>