C++之父 Bjarne 最新發(fā)聲:21世紀(jì)代碼該怎樣寫(xiě)?
本文根據(jù) Bjarne Stroustrup 的最新文章“21st Century C++”內(nèi)容進(jìn)行歸納總結(jié),總結(jié)了現(xiàn)代 C++(尤其是 C++20/23/30 版本)在語(yǔ)法特性、資源管理、模塊化、泛型編程以及編程準(zhǔn)則等方面的重要進(jìn)展。希望能幫助讀者更好地理解當(dāng)代 C++ 的核心理念,并在實(shí)際開(kāi)發(fā)中落地應(yīng)用。

前言:為何需要“21世紀(jì)的 C++”?
C++ 自 1979 年構(gòu)思至今,已有 40 多年歷史。在這漫長(zhǎng)的發(fā)展過(guò)程中,C++ 保留了與早期版本的兼容性,卻也不斷進(jìn)化,新增了許多語(yǔ)言特性和標(biāo)準(zhǔn)庫(kù)功能。Bjarne Stroustrup 在其文章中強(qiáng)調(diào):
- 兼容性是 C++ 的重要特征,老代碼幾乎無(wú)需修改就能繼續(xù)運(yùn)行。
- 但如果僅停留在上世紀(jì)末的使用方式,往往會(huì)降低開(kāi)發(fā)效率,并產(chǎn)生許多安全與性能隱患。
因此,面向“21 世紀(jì)”的現(xiàn)代 C++(尤其是 C++20/23/30)在語(yǔ)言理念和應(yīng)用實(shí)踐上,都提出了 更簡(jiǎn)潔、更安全、更可維護(hù)、更高性能 的方案。例如 RAII(自動(dòng)資源管理)、模塊(module)、概念(concept)等。通過(guò)合理使用這些現(xiàn)代特性與指導(dǎo)原則,我們可以寫(xiě)出既簡(jiǎn)潔又安全、既通用又高性能的 C++ 代碼。
一、C++ 理想與關(guān)鍵特性
1. C++ 理想
Stroustrup 總結(jié)了 C++ 設(shè)計(jì)與實(shí)踐所追求的幾個(gè)主要目標(biāo)(從 1980 年代至今基本未變):
- 直接表達(dá)抽象:讓程序員能直接表達(dá)所思考的概念,不必屈從于底層實(shí)現(xiàn)細(xì)節(jié)。
- 靜態(tài)類(lèi)型安全:在編譯期捕獲盡可能多的錯(cuò)誤;類(lèi)型錯(cuò)誤越早發(fā)現(xiàn)越好。
- 資源安全(RAII):通過(guò)對(duì)象的構(gòu)造與析構(gòu)自動(dòng)管理資源,避免泄漏和手動(dòng)釋放的不確定性。
- 零開(kāi)銷(xiāo)抽象:抽象不能帶來(lái)額外的性能負(fù)擔(dān),“用不到就不付費(fèi),用到也只付最少的代價(jià)”。
- 直接訪(fǎng)問(wèn)硬件:對(duì)底層系統(tǒng)的可控性和可移植性。
- 可維護(hù)性:代碼可讀、易于修改;同時(shí)兼顧高性能和大規(guī)模項(xiàng)目需求。
- 平臺(tái)獨(dú)立:跨平臺(tái)特性?xún)?yōu)先。
- 穩(wěn)定性/兼容性:保證老代碼能在新環(huán)境下繼續(xù)運(yùn)行。
基于這些理想,C++ 從早期的面向?qū)ο筇匦裕╟lass/繼承/虛函數(shù))一路演進(jìn)到模板、泛型編程、lambda、概念(concepts)、模塊(modules)等,不斷擴(kuò)展著語(yǔ)言應(yīng)用邊界。
2. 老特性與新特性
C++ 的一些“老”特性(class、構(gòu)造/析構(gòu)、異常、模板、std::vector 等)依舊是當(dāng)代 C++ 程序的基石;而一些“新”特性(模塊、概念、lambda、ranges、constexpr/consteval、并發(fā)庫(kù)、協(xié)程等)正為應(yīng)用開(kāi)發(fā)提供更加靈活且更高層次的抽象支持。
注意:并非只有最新特性才是“好”的,關(guān)鍵在于恰當(dāng)組合,并遵守現(xiàn)代編程準(zhǔn)則。
二、資源管理:RAII 與異常處理
1. RAII 核心原則
RAII(Resource Acquisition Is Initialization)是現(xiàn)代 C++ 保證資源安全的重要基礎(chǔ)。其本質(zhì)是:
- 構(gòu)造函數(shù)中完成資源獲取,
- 析構(gòu)函數(shù)中完成資源釋放,
- 通過(guò)作用域退出來(lái)自動(dòng)釋放資源,從而避免手動(dòng)釋放的麻煩與風(fēng)險(xiǎn)。
舉個(gè)簡(jiǎn)單例子,一個(gè)自定義 Vector 若自己管理內(nèi)存,就應(yīng)在構(gòu)造函數(shù)中分配,在析構(gòu)函數(shù)中回收,以防止內(nèi)存泄漏;而在函數(shù)調(diào)用棧退棧時(shí),Vector 會(huì)自動(dòng)析構(gòu),從而釋放資源。
2. 避免裸指針與顯式 new/delete
如果在函數(shù)中直接使用 new 返回裸指針,一旦在中途拋異?;蚝瘮?shù)提前返回,資源就容易泄漏。現(xiàn)代 C++ 強(qiáng)調(diào):
- 盡量使用容器(例如 std::vector),或
- 使用智能指針(例如 std::unique_ptr、std::shared_ptr)。
從而減少甚至杜絕顯式 delete。加之異常處理(exception)或錯(cuò)誤碼檢測(cè),可以有效防止資源泄漏和懸空指針(dangling pointer)的問(wèn)題。
3. 錯(cuò)誤處理:異常 vs. 錯(cuò)誤碼
C++ 的異常是一種自帶棧展開(kāi)(unwinding)并自動(dòng)調(diào)用析構(gòu)的機(jī)制,可以“保證 RAII 不失效”。它比較適用于無(wú)法在本地處理的“真正異?!眻?chǎng)景。同時(shí),對(duì)那些在函數(shù)局部就能處理好的小錯(cuò)誤,可以使用返回值或錯(cuò)誤碼進(jìn)行判斷。
Stroustrup 強(qiáng)調(diào),不必在所有情況下都只用返回值或只用異常,這兩者各有適用場(chǎng)景。
三、模塊化與 import
1. 頭文件與宏的歷史問(wèn)題
C++ 繼承了 C 的預(yù)處理器(#include 和宏),它給“模塊化”帶來(lái)很多隱患:
- 包含次序敏感:同樣的頭文件順序不同可能帶來(lái)不同結(jié)果。
- 包含過(guò)載:一個(gè)大型頭文件往往被重復(fù)編譯多次,浪費(fèi)編譯時(shí)間。
2. 模塊(Modules)優(yōu)勢(shì)
現(xiàn)代 C++(C++20 起)引入了原生“模塊”概念:
- import 的順序不影響編譯效果,避免了頭文件中宏定義與嵌套包含的混亂。
- 一次編譯后即可重復(fù)使用,大幅減少重復(fù)編譯時(shí)間。
Stroustrup 舉的例子表明,一個(gè)包含 40~50 萬(wàn)行的巨型庫(kù),如果由傳統(tǒng)的 #include 方式引入,編譯需要 1.5 秒×N;而換用 import 后或只需編譯一次,就能在之后的多個(gè)源文件中快速?gòu)?fù)用,可能只耗時(shí)幾十分之一甚至更少。
對(duì)于大型工程,采用模塊化改造雖然需要投入,但能極大改善編譯性能與可維護(hù)性。
四、泛型編程與概念(Concepts)
1. 泛型編程在標(biāo)準(zhǔn)庫(kù)中的應(yīng)用
C++ 標(biāo)準(zhǔn)庫(kù)中大量使用模板來(lái)實(shí)現(xiàn)容器(std::vector、std::list……)、并發(fā)(std::thread、std::jthread……)等特性,其理念是:一次編寫(xiě),適應(yīng)多種類(lèi)型。但傳統(tǒng)模板檢查時(shí),錯(cuò)誤信息往往冗長(zhǎng)而晦澀。
2. 概念(Concept)的引入
C++20 帶來(lái)的“概念”提供了一種“更清晰”的模板形參約束方式。
- 概念本質(zhì)上是一個(gè)在編譯期執(zhí)行的布爾函數(shù),用來(lái)判斷某個(gè)類(lèi)型是否滿(mǎn)足特定接口/用法要求。
- 這讓模板的可讀性和錯(cuò)誤提示大幅提升。
template<Sortable_range R>
void sort(R& r) { /* ... */ }若傳入一個(gè)不滿(mǎn)足 Sortable_range 的類(lèi)型,例如 std::list,編譯期就能給出更準(zhǔn)確的錯(cuò)誤位置,而不再是一長(zhǎng)串模版展開(kāi)報(bào)錯(cuò)。
3. constexpr 與 consteval
C++20 還強(qiáng)化了編譯期計(jì)算的能力:
- constexpr:可在編譯期求值,也可在運(yùn)行期執(zhí)行。
- consteval:必須在編譯期執(zhí)行。
- 概念(concept)也是類(lèi)似的“編譯期布爾函數(shù)”。
這些機(jī)制讓我們可以在編譯階段就完成更多邏輯,從而減少運(yùn)行期開(kāi)銷(xiāo),或盡早捕獲錯(cuò)誤。
五、編程準(zhǔn)則與“Profile”機(jī)制
1. 為什么需要“準(zhǔn)則”?
C++ 雖然強(qiáng)大,但也常被詬病“太復(fù)雜”,且有些老式用法帶來(lái)安全風(fēng)險(xiǎn)。例如:
- 數(shù)組越界、裸指針懸空、重復(fù)釋放……
- 不恰當(dāng)?shù)念?lèi)型轉(zhuǎn)換、隱式轉(zhuǎn)換導(dǎo)致的微妙 Bug……
而編譯器本身又不能硬性禁止所有潛在不安全用法(因?yàn)橐嫒葸z留代碼)。因此,“編程準(zhǔn)則”就成了提升代碼安全與質(zhì)量的必經(jīng)之路。
2. C++ Core Guidelines
Stroustrup 牽頭的 “C++ Core Guidelines” 提供了一系列核心規(guī)則,涵蓋資源管理、智能指針、容器與迭代器、異常安全等方方面面。主要目標(biāo)是:
- 默認(rèn)禁止不安全用法(如裸指針遍歷數(shù)組、顯式 delete 等),
- 在必要時(shí)可以使用更底層、更靈活的方式,
- 通過(guò)靜態(tài)檢查(分析工具)+ 運(yùn)行時(shí)檢查(必要的邊界檢測(cè))來(lái)確保規(guī)則得以貫徹。
3. Profile:強(qiáng)制化子集
有了準(zhǔn)則,為了讓它真正落地,社區(qū)和標(biāo)準(zhǔn)委員會(huì)提議了“Profile”方案,即:
- Profile 是一組可被工具強(qiáng)制執(zhí)行的規(guī)則集合。
- 可以針對(duì)不同應(yīng)用領(lǐng)域(比如嵌入式、安全關(guān)鍵系統(tǒng)等)選擇適合的 Profile,編譯器或靜態(tài)分析工具會(huì)拒絕不符合該 Profile 的寫(xiě)法。
比如,[[profile::enforce(type)]] 告訴編譯器“不允許任何隱式轉(zhuǎn)換或類(lèi)型不安全的操作”,并在檢測(cè)到時(shí)進(jìn)行報(bào)錯(cuò)。這種做法能最大化地利用現(xiàn)代 C++ 優(yōu)勢(shì),同時(shí)仍能在需要時(shí)提供后門(mén)(可局部 suppress 規(guī)則)。
六、未來(lái)發(fā)展
Stroustrup 在文章末尾提到,目前社區(qū)正持續(xù)推動(dòng)以下方向:
- 并行與異步計(jì)算:讓數(shù)據(jù)并行/任務(wù)并行更易用、更安全。
- 靜態(tài)反射:編譯期能獲取更多關(guān)于類(lèi)型與成員的信息,類(lèi)似“編譯期元編程”。
- 契約(Contract):在函數(shù)接口層面可聲明“先決條件/后置條件”,讓編譯器或運(yùn)行時(shí)更好地檢測(cè)邏輯錯(cuò)誤。
- 模式匹配(Pattern Matching):借鑒函數(shù)式語(yǔ)言或其他語(yǔ)言特性,為分支邏輯提供更直觀的寫(xiě)法。
- 單位/量綱庫(kù):讓物理量、單位換算在語(yǔ)言層面更好地表達(dá),減少人為換算出錯(cuò)。
這些特性都在活躍討論中,部分已有實(shí)驗(yàn)/提案版實(shí)現(xiàn)。
總結(jié):擁抱當(dāng)代 C++
從上世紀(jì)的 C with Classes,到如今的 C++20/23/30,C++ 已經(jīng)走過(guò)了漫長(zhǎng)的演化之路。它并非只是“面向?qū)ο蟆被颉澳0寰幊獭?,而是一個(gè)融合多范式(過(guò)程式、面向?qū)ο蟆⒎盒?、函?shù)式、元編程等)的大工具箱。
如果你還在使用 90 年代甚至更早風(fēng)格的 C++,可以嘗試逐步過(guò)渡到現(xiàn)代寫(xiě)法:
- 資源管理:優(yōu)先使用標(biāo)準(zhǔn)容器和智能指針,借助 RAII 保證安全和簡(jiǎn)潔。
- 模塊化:告別龐大的頭文件和復(fù)雜的編譯依賴(lài),嘗試 import 來(lái)替代大量 #include。
- 泛型與概念:利用 concept 提升可讀性和模板類(lèi)型安全。
- 編程準(zhǔn)則:引入 C++ Core Guidelines,使用工具(靜態(tài)/動(dòng)態(tài)分析)幫你自動(dòng)檢測(cè)不安全用法。
- Profile:期待標(biāo)準(zhǔn)落地后,可進(jìn)一步強(qiáng)制或部分強(qiáng)制在項(xiàng)目中執(zhí)行安全子集,讓 C++ 更易維護(hù)。
C++ 的發(fā)展離不開(kāi)眾多程序員的實(shí)踐與反饋,也離不開(kāi)生態(tài)和工具的共同完善。對(duì)個(gè)人或團(tuán)隊(duì)而言,掌握并踐行“21 世紀(jì) C++”的核心理念,是寫(xiě)出高質(zhì)量、可維護(hù)且高效的代碼之關(guān)鍵。
























