C++發展得非常快!例如,C++標準的頁數從 C++98/03 的 879 頁增加到了 C++20 的 1834 頁,多了近 1000 頁!更重要的是,C++每次修訂后,我們都會獲得幾十個新特性。你需要學習所有這些東西才能寫出好代碼嗎?如何在當今的 C++世界中保持理智?
介紹你可能知道 C++是一種復雜的語言。我甚至發現了一整頁Wiki是講對 Cpp 的批判的。現代 C++甚至為生態添加了更多內容。
以下是我之前提到的規范頁數的完整數據:
C++98/03-879,N1905,2005 年 10 月
C++11-1324,最后草案,N3337,2012 年 1 月
C++14-1368,最后草案,2014 年 11 月
C++17-1586,草案,N4606
C++20-1834,草案,N4861
看起來 C++17 幾乎比 C++98/03“大”了 80%,而 C++的最新草案比 C++03 多了將近 1000 頁。你可以抱怨增加的這些復雜性,想學好所有這些東西也很困難。但這有那么可怕嗎?面對這樣的情況,你能做些什么?
首先,我們來看看你在 C++中可能會遇到的一些問題。
一些問題僅舉幾例:
節奏太慢
節奏太快
特性的混亂/復雜性
編譯時間慢
缺乏依賴管理
我們來仔細研究一下。
節奏太慢2017 年,我們迎來 C++17。雖然每三年就迎來一個新標準是很棒的,但許多開發人員抱怨新版本并不是每個人都期待的。
很多特性:比如概念(concept)、模塊、范圍(range)、協程(co-routine)……都沒有被接受,我們至少需要再等三年才能讓它們進入規范。
在 2020 年,C++20 已經準備就緒,并且這些重要特性將隨編譯器一起提供!但我們還是會抱怨合約(contract)還沒加進來,反射(reflection)、執行器(executor)或網絡(networking)仍在討論中。它們可能出現在 C++23 甚至更高版本中。
看起來有些特性接受起來比較慢……而且總有東西值得抱怨。
節奏太快像往常一樣,我們在這里可能有兩種相互矛盾的意見。盡管對某些人來說升級節奏很慢,但對其他人來說卻很難跟上變化。
你剛剛學習了 C++11/14……現在你就需要更新 C++17 的知識,然后 C++20 就在路上了。三年并不是那么短的時間,但請記住,編譯器一致性、公司政策、團隊指南可能會以不同的節奏前進。
你的公司是立即更新到最新的 C++版本還是等待幾年?
特性的混淆/復雜性只需閱讀這條評論:
CallMeDonk:
我喜歡 C++。這是我的首選語言,但你必須承認,它對值類的“大雜燴”實現是很怪異的。包括我在內的大多數程序員更喜歡簡單的、定義明確的語言結構,而不是奇怪和復雜的語法。
C++在各個方面都很清晰嗎?可能不是……
以下是一些可能難以理解并可能讓程序員糊涂的主題:
移動語義移動語義的原則非常明確:不要復制,而是嘗試“竊取”托管資源的內部結構,你應該獲得不錯的性能提升。但魔鬼都藏在細節中。
我不會寫很多通用代碼,所以幸運的是,我不必一直考慮移動語義。但是,當我遇到 move 和 const 時會很困惑——請參閱我上一篇關于該主題的文章。我不相信所有 C++開發人員都會理解這里的規則。特別是你現在需要記住編譯器生成的六個默認操作:默認構造器、析構函數、復制構造器、移動構造器、賦值運算符和移動賦值運算符。
Rvalues/xvalues/prvalues……myValues、fooValues最后一個是我編的……但那么多值類別實在太讓人頭疼了!
在 C(或 C++98/03)中,你只需要知道左值與右值,現在它有點微妙了。
不過,問題是你是否需要記住它?
一些不錯的評論:
c0r3ntin:
初始化這很復雜,但不是每天都能遇到。這個值可以 address 嗎?可以復制嗎?可以移動嗎?應該移動嗎?只有在極少數情況下,你才需要主動去澄清并充分理解它們。(模板化庫編寫、熱路徑等)。大多數時候 C++并不比 java 或其他東西復雜。可悲的是大多數人都忘了這一點。C++可能是最復雜的語言,但是你可以編寫非常好的代碼而無需關心具體的細節。BigObject o=getBigObject();
現在有 18 種方式(從 C++17 開始)!
參閱:C++中的初始化是瘋狂的;r/cpp線程
模板(和模板推導)當我看到 C++17 的所有變更時,我很迷茫;關于模板的細節太多了。
同樣的情況發生在 C++20 中,我們迎來了一個重大且期待已久的改進:概念——它徹底改變了 C++。
然而,如果你想學習模板,一開始可能會不知所措。
ABI隨著新特性列表的不斷增長,“從頭開始”修復 C++設計中的舊問題可能是很誘人的主題。但這種語言的原則是不能破壞舊代碼,所以委員會非常嚴格,不喜歡改變已引入特性的路線。
這個問題沒有正確的答案,但無論如何,一個經過充分討論的主題要比倉促的舉動更好。
缺乏依賴管理工具我們可以抱怨 C++沒有“交?付”一個很酷的依賴管理系統。但現實情況是,在可預見的未來,這可能都不會實現。擁有一個“標準”的包管理器是一個艱難的選擇,尤其是它必須處理如此多的可用 C++的平臺和系統。
不夠安全前段時間,你可以讀到提到這個問題的一些文章(這篇和這篇):
谷歌工程師本周表示,Chrome 代碼庫中大約 70%的嚴重安全漏洞是內存管理和安全漏洞。
微軟也是如此。由于大部分代碼是 C 或 C++,所以每個人都指責 C++不夠安全。
其他問題?你在這種語言上遇到的主要問題都有哪些?
到目前為止,我們已經討論了一些問題……那么如何應對它們呢?有機會解決這些問題嗎?
如何保持理智沒有完美的編程語言;每種語言都有一些問題。以下是我關于如何處理現代 C++問題的建議:
保持樂觀
使用最佳指南
使用最好的工具
跟上最新進展
不要打開引擎蓋
使用你需要的
增量變更
最后的底線:你的舊代碼仍然安全并且可以編譯
保持樂觀,語言在不斷發展沒有人愿意使用舊的語法和結構來編寫代碼。我們已經看到很多關于 C++11 之前的舊版 C++的抱怨。人們花了將近 13 年的時間(從主要的 C++98 算起,不包括次要的 C++03)才提出新的主要版本:C++11。現在我們可以很高興回到了正軌,每三年都會有一些變化。歸根結底,你不能說你的語言已經死了。
雖然某些特性非常龐大,可能會帶來混亂或需要學習更多東西,但實際情況其實很簡單:
在 C++03 之后添加的 1000 個新頁面中的大部分用于標準庫。這意味著你可以使用更多助手和子系統,而無需查找第三方庫。這絕對會讓你的生活更輕松。
對于移動語義,你可以依賴庫類型,因為它們會為你完成正確的工作。例如,你現在可以安全地返回std::vector并確保它可能被移動甚至被刪除,而無需額外副本。
至于模板,它變得越來越容易使用。概念讓代碼更安全,沒有像 SFINAE 這樣的技巧。更重要的是,我們有了constexpr和auto,讓泛型代碼更簡單了(幾乎就像常規代碼一樣)。
至于安全性:在這里查看 C++指南的安全配置文件的自動化工具。C++ Core Check中的新安全規則|C++團隊博客。我們可以期待新的、更好的工具來執行代碼分析甚至檢測,以盡快發現潛在的安全問題。或者看這篇文章:使用靜態分析原理縮小Rust和C++之間的差距——SunnyChatterjee——CppCon
使用指南如果你對 C++代碼的許多方面都感到困惑,那么你應該查閱 C++核心指南。它由熱心的 C++開發社區創建,主要編輯是 Herb Sutter 和 Bjarne Stroustrup。
看這里:
C++核心指南@Github
這里有一個漂亮的網站:
C++核心指南:網站
只需輸入你面臨的問題(例如return value),你就可以輕松找到建議——例如:指南:返回值
使用這些指南將為你節省大量時間,并且你可以非常快地學習一些好的模式。
還有工具!感謝 Clang 以及其他平臺上的開發速度提升,我們獲得了如下工具:
ClangTidy(以前是 clang-modernise)
Clang Format
Clang Static Analyzer
VisualAssist
Clion/ResharperC++
VisualStudio——像C++ Core Checker這樣的工具
PVS Studio
用于 VisualStudio 的Clang Power Tools
新的C++核心檢查規則|C++團隊博客
C++核心指南檢查器參考|微軟文檔
介紹vcperf/timetrace,用于C++構建時間分析|C++團隊博客
C++ Core Check中的新安全規則|C++團隊博客——C++和 Rust 一樣安全嗎?
或者查看我關于其他工具的文章:C++生態系統:編譯器、IDE、工具、測試等
雖然它不像其他語言(主要基于 Java 或基于.NET)那么好,但它正在變得越來越好。請記住,由于 C++語法復雜,因此很難實現即時分析代碼的工具。
努力跟上最新進展C++社區非常活躍。有很多博客、書籍、會議……甚至有可能在你所在的城市有本地社區。
首先,我建議去 isocpp.org 查看所有事件/新聞/文章。然后你可以查看Meeting C++和有關本地C++小組的信息。還有reddit/cpp,你可以在那里看到一些最棒的 C++故事。
還有CppCast——一個針對 C++開發人員的每周播客。
并參考以下書籍:
C++編程語言第4版
高效的現代C++
編程:使用C++的原理和實踐
發現現代C++:科學家、工程師和程序員的強化課程
C++之旅(C++深入系列)第2版
你還可以查看推薦的 C++資源列表:
Bartek的編程博客:資源
細節太多了?C++如此強大的原因之一是它允許你實現非常接近底層的代碼。你可以控制所有細節、內存布局、性能優化等……同時,這些能力增加了語言的復雜性。
不過,如果你不需要走那么遠,你可以停留在相對較高的抽象級別。
例如,你不需要編寫可選類型,因為你可以使用標準庫中的std::optional。如果你不想涉及低級別和容易出錯的聯合類型,你應該意識到std::variant是一個安全的選項。
使用你需要的東西C++是一種多范式語言;你可以以多種不同的方式使用它。最近,我讀到了一條有趣的評論,說 Cpp 程序員在不接觸模板元編程甚至異常等高級內容的情況下,也能持續多年表現出色。這在很大程度上取決于項目的代碼風格。
例如,即使像谷歌這樣的公司也限制了 C++的特性,比如說他們不使用異常。
如果你不是庫開發人員,你可能不會遇到自定義移動運算符或移動構造器的麻煩。同樣,高級元編程的內容也可能不是你的代碼的關鍵部分。
增量變更如果你是從頭開始或只有一個小的代碼庫,那么轉到 C++11/14 應該相對容易一些。可是 20 年(或更久!)前開始創建的上百萬行代碼呢?
只需一步一步來就行了。
至少對于新代碼,你應該開始使用現代 C++。此外,通過應用“童子軍規則”,你可以改進你所接觸的那些代碼。
這可能會帶來一些混合代碼,但還是比只保留老舊風格要好。
最后的底線:你的舊代碼仍然可以編譯C++規范越來越大的原因之一是該語言向后兼容。所以委員會通常會引入新特性,但很少刪除舊的東西。所以……你的代碼仍然可以編譯。如果你不想前進,不想使用新的東西,那么你還是可以保持當前的風格。
有時你會收到一些關于不推薦使用的內容或刪除特性的警告(如 C++17 中的auto_ptr),但即使在這種情況下,你也可以將編譯器切換到一些較舊的 C++標準。
總結這篇文章有一些抱怨,也有一些“美化”。我試圖找出這種語言及其演變過程中存在的各種問題,以及一些積極的改進跡象。雖然我們可以抱怨復雜性、變化的速度等,但我認為我們不能說這種語言已經死掉了。這是好事!:)
我認為你不必快速追逐新特性并立即重寫現有代碼。試著跟上進展,使用真正改進你工作的特性,你的代碼應該逐漸改進并變得更加“現代化”(這是可以定義的,請參閱 meetingcpp 的相關文章)
在采用 C++11/14/17/20 的新特性時,你的方法是什么?
你使用 C++的主要問題是什么?
你在工作中使用現代 C++嗎?
以下是一些常見的C語言靜態測試工具:
1. Splint:免費的開源靜態分析工具,支持C程序,可以檢查類型安全、資源泄漏、未初始化變量等常見問題。
2. PC-lint:商業靜態分析工具,支持C和C++程序,可以在編譯時或運行時檢查代碼中的問題,例如不兼容的指針類型、內存泄漏等等。
3. Clang:C語言的靜態分析工具,可用于錯誤檢查、代碼重構和查找代碼中的重復。
4. Cppcheck:免費的開源靜態分析工具,支持多渠道途徑,適用于C和C++程序,可檢查未分配的內存、數組越界、指針使用或數值溢出等問題。
5. Flawfinder:免費的開源程序,適用于C和C++程序,可以查找常見的安全漏洞、編碼風格錯誤和未定義的行為等。
6. Coverity:一種商業靜態分析工具,支持多種編程語言,包括C語言,可用于檢查缺陷、安全漏洞和性能問題等。
這些工具可以幫助程序員在代碼開發周期的不同階段檢測代碼中的錯誤和問題,從而提高代碼質量和可靠性。