C++ 之父 2024 年末重磅演講 | 重新認識 C++:跨世紀的現代演進

作者 | 《新程序員》編輯部

出品 | CSDN(ID:CSDNnews)

12 月 5 日,美國國家工程院、ACM、IEEE 院士、C++ 之父 Bjarne Stroustrup 在「2024 全球 C++ 及系統軟件技術大會」上發表了題為《重新認識 C++:跨世紀的現代演進》的演講。屏幕上,演示文稿的第一頁就令人印象深刻:「C++ 幾乎可以實現我們所期望的一切!

從構建操作系統到開發高性能遊戲引擎,從支持人工智能框架到驅動航天器控制系統,C++ 一直是系統級軟件開發的首選語言。然而,這位編程語言大師並不是在炫耀 C++ 的強大,而是要指出一個關鍵問題:「正因為它如此強大,我們更要謹慎選擇正確的使用方式。就像 goto 語句——它無所不能,所以我們幾乎從來不用它。同樣的,雖然用 20 世紀 80 年代的方式寫 C++ 也能完成任務,但這顯然不是最佳選擇。我們需要明確自己的真正需求,避免重蹈覆轍。

Stroustrup 指出了一個常見的認知誤區:人們往往把「熟悉」等同於「簡單」對很多開發者來說,見過千百遍的代碼寫法看起來簡單,而新的特性和方法則顯得複雜。

「我們必須努力避免這種思維定式,否則就會永遠停留在 20 世紀。」他強調道,「今天,我想談談我所認為的當代 C++、現代 C++ 的基礎是什麼。我認為,當代的編程方式能讓代碼變得更簡單、更安全、更高效,遠勝於任何舊版本的 C++。(在這一語境下,「當代」往往指的是 C++20/23/26 等當前的版本)

當代 C++ 的簡潔之美

為了說明當代 C++的優勢,Stroustrup 首先以他收到的一個來自《龍書》(Dragon Book,編譯器設計領域的經典教材作者、AWK 語言的創造者之一 Alfred V. Aho 的難題為例。這個例子展示了如何用 C++ 簡潔地處理文本中的不重覆行:

import std;using namespace std;
int main()   // 輸出輸入流中的不重覆行{    unordered_map<string,int> m; // 哈希表    for (string line; getline(cin,line); )        if (m[line]++ == 0)            cout << line << '\n';}

「這段代碼展示了幾個重要特點,」Stroustrup 解釋道,「首先,完全沒有使用預處理器;其次,代碼高效且容易理解;第三,如果需要進一步優化,也完全可以做到——但關鍵是,在開始優化之前,這段代碼本身就已經相當高效了。」

「讓我們試試另一種處理不重覆行的方式。」他進一步提出,「為什麼要一直輸出行呢?也許我想要的是一個僅僅收集輸入中不重覆行的程序。」

這樣一個簡單函數就能輕鬆實現:

vector<string> collect_lines(istream& is) // 從輸入中獲取不重覆行{    unordered_set<string> m; // 哈希表    for (string line; getline(is,line); )        m.insert(line);    return vector(m.begin(),m.end());}auto lines = collect_lines(cin);

「C++ 的類型系統會自動推導出我們需要的是 string 的 vector,」Stroustrup 解釋說,「而且返回時不需要複製,直接移動就行了。這樣的實現既簡潔又高效。」

「但這裏的 vector 構造有點囉嗦。我希望 vector 能直接接受這個集合本身,」Stroustrup 說,「所以我寫了一個函數,它可以接受任何範圍並從中創建 vector。」於是他展示了一個更簡潔的版本:

vector<string> collect_lines(istream& is) // 從輸入中獲取不重覆行{    unordered_set<string> m; // 哈希表    for (string line; getline(is,line); )        m.insert(line);    return make_vector(m);}auto lines = collect_lines(cin);

「標準庫不需要提供所有功能。有時候自己寫個簡單函數就能解決問題,比如這個 make_vector。」他最終總結道,「也許在 C++ 的未來版本中,vector 會直接支持這種構造方式,那時這個函數就不需要了。」

「從這些例子可以看出我最重視的一點:思想的直接表達。」Stroustrup 緊接著列出了他重視的每一項事物:

談到 C++ 的發展歷程,Stroustrup 指出:「一些關鍵特性和技術已有多年歷史,比如帶構造函數和析構函數的類、異常處理機制、模板、std::vector……等等。另一些則是較新的發展,如 constexpr 函數和 consteval 函數、lambda 表達式、模塊、概念、std::shared_ptr……等等。關鍵在於將這些特性作為一個整體來運用。

「不要盲目使用所有新特性,也不要局限於僅使用新特性,」他強調道,「如果想瞭解最新特性和未來發展方向的更多細節,可以參考相關的技術討論影片。我更關注的是如何將語言作為一個整體來開發好的軟件。因為最終編程語言的價值體現在其應用程序的質量之中。

資源管理:C++ 的基石

我們知道,相比歸還東西,人們更傾向於獲取東西,Stroustrup 首先打了個生動的比方,「問任何一個圖書管理員就知道了,人們借書後常常忘記還書。在大型軟件中,如果我們必須顯式地返還借用的資源,我們肯定會遺漏一些。

Stroustrup 將資源定義為「任何必須獲取並在之後釋放(歸還)的對象」。「這包括內存、string(字符串)、互斥鎖、文件句柄、套接字、線程句柄、著色器等等很多東西,」他解釋道。「從這個詞的含義來看,在編程中我們要處理的很多東西都是資源。」

在 C++ 中,每個資源(resource)都應該有對應的句柄(handle)來管理它的生存期。句柄負責資源的訪問和釋放,這種機制是通過對生存期的嚴格控制來實現的

為瞭解決這個問題,Stroustrup 提出了幾個關鍵原則:

1. 避免手動釋放資源——不要在應用程序代碼中出現 free()、delete 等資源釋放操作;

2. 使用資源句柄——每個對象都由負責訪問和釋放的句柄管理;

3. 基於作用域管理——所有資源句柄都屬於特定作用域,可以在作用域間轉移;

他用一段簡單但富有啟發性的代碼來說明這些原則:

template<typename T>class Vector { // T 類型元素的 vectorpublic:    Vector(initializer_list<T>); // 構造函數:分配內存並初始化元素    ~Vector(); // 析構函數:銷毀元素並釋放內存    // ...private:    T* elem; // 指向元素的指針    int sz;  // 元素數量};
void fct(){    Vector<double> constants {1, 1.618, 3.14, 2.99e8};    Vector<string> designers {"Strachey", "Richards", "Ritchie"};    // ...    Vector<pair<string,jthread>> vp { {"producer",prod}, {"consumer",cons}};}

「這就是 C++ 的基石構造函數constructor)和析構函數(destructor),」Stroustrup 說道,「如果需要獲取任何資源,那是構造函數的工作;如果需要歸還資源,那是析構函數的工作。這裏我們將抽像層次從機器級的指針和大小提升到了更高的層次。我們把它包裝成一個類型,這個類型行為正確,有賦值操作,有訪問函數,並且能正確清理。

他特別指出了資源管理機制的遞歸性:「string 擁有一些字符,這裏的 pair 擁有一個 string 和一個 jthread。jthread 擁有對操作系統線程的引用。這些都是遞歸進行的。神奇之處在於最後的閉合花括號——那裡是所有東西都被隱式而可靠地清理的地方。

為了做好資源管理,Stroustrup 強調了對生存期的控制:

  • 構造:首次使用前建立對象的不變量(如果有的話);

  • 析構最後使用後釋放所有資源(如果有的話);

  • 複製a = b 意味著 a == b,且它們是獨立的對象;

  • 移動在作用域間轉移資源擁有權;

「這些機制讓我們能夠開發出更安全、更可靠的代碼,」他總結道,「因為資源管理不再依賴於程序員的記憶力,而是由語言機制自動保證。

錯誤處理的策略

「在確保資源安全的基礎上,我們還需要有明確的錯誤處理(error handling)策略,」Stroustrup 隨即轉入了另一個重要話題。他指出,C++ 中有兩種主要的錯誤處理方式,它們各有適用場景:

「對於那些常見且可在局部處理的失敗情況,使用錯誤碼(error code)是合適的,這種方式避免了使用效率低下且醜陋的 try-catch 結構」他解釋了第一種情況,但問題是,我們經常忘記檢查錯誤碼,這可能導致錯誤的結果繼續傳播。而且,這種方式不適用於構造函數和運算符。比如說,當你寫 Matrix x = y + z 這樣的表達式時,就沒有地方放置錯誤返回語句和測試。

「另一方面,對於那些罕見且無法在局部處理的錯誤,異常處理(exception handling)是更好的選擇。」Stroustrup 繼續說道,「錯誤可以沿調用鏈向上傳播,避免陷入 ‘錯誤碼地獄’。未捕獲的異常會導致程序終止,而不是產生錯誤結果。重要的是,這種機制必須與 RAII(資源獲取即初始化)配合使用,依賴作用域資源句柄。

他用一個具體的例子說明了這個觀點:

void fct(jthread& prod, string name){    ifstream in { name };    if (!in) { /* ... */ }  // 預期可能發生錯誤
    vector<double> constants {1, 1.618, 3.14, 2.99e8};  // 內存可能耗盡    vector<string> designers {"Strachey", "Richards", "Ritchie"};  // 嵌套構造
    jthread cons { receiver };    pair<string,jthread&> pipeline[] { {"producer", prod}, {"consumer", cons}};    // ...}

「想像一下,如果只使用單一的錯誤處理方式,這段代碼會變得多麼複雜,」Stroustrup 說,每個操作都可能失敗:文件打開可能失敗,內存分配可能失敗,構造過程可能失敗。使用異常處理,我們可以集中處理這些錯誤,而不是在每個可能的失敗點都編寫檢查代碼。

Stroustrup 還提到了一個最新的研究發現:「即便對小型系統,異常處理也可能比錯誤碼更高效。我們最近看到一個很好的演示,展示了在小型固件中使用 C++ 異常可以產生更小、更快的代碼。

「關鍵是要記住,」他強調,「錯誤處理不是要選擇唯一正確的方式,而是要根據具體情況選擇最合適的方式。有時是錯誤碼,有時是異常,重要的是要有一個明確的策略。即便對小型系統,異常處理機制也可能比錯誤碼更高效。Khalil Estell 最近在 CppCon 2024 上的演示*展示了在小型固件中使用 C++ 異常可以產生更小、更快的代碼。

* Khalil 的演講內容:https://www.youtube.com/watch?v=bY2FlayomlE

模塊:打破「包含」的魔咒

談到代碼組織,Stroustrup 首先指出了一個困擾 C++ 開發者多年的問題:「頭文件包含的順序依賴問題一直是個麻煩。#include “a.h” 後跟 #include “b.h”,可能與順序顛倒後的結果完全不同。這種基於文本的包含機制會導致:包含具有傳遞性、相同的代碼被重覆編譯多次、容易引發宏定義衝突等問題。

相比之下,C++20 引入的模塊(modules)機制則完全不同:

import a;import b;

「這與順序無關,」Stroustrup 解釋道,「寫成下面這樣,效果完全一樣。」

import b;import a;

import 不具有傳遞性,模塊化的代碼更加乾淨,而且能顯著提升編譯速度——這不是百分比級的提升,而是數量級的提升。

緊接著,他興奮地宣佈:經過幾十年,我們終於在 C++ 中實現了模塊。我們不必再使用 include 了!這是我長期計劃的一部分——逐步淘汰 C 預處理器。預處理器會給工具帶來麻煩,因為工具看到的和程序員看到的是不一樣的。

他分享了來自一家德國嵌入式系統公司的實際案例。該公司有一個傳統的設備信息庫 libgalil,通過頭文件包含機制,最終會展開成約 50 萬行代碼(其中 15 萬行是空行)。即便以現代編譯器的速度,處理這樣的代碼也需要 1.5 秒。然而,當他們將其改造為模塊後,預處理後只有 5 行代碼,編譯僅用了 62 毫秒,實現了 25 倍的速度提升。

「當然,你不能期待在所有情況下都能獲得 25 倍的提升,」Stroustrup 說,「但根據經驗,使用具名模塊通常能讓編譯速度提高 7-10 倍。這就是促使人們將代碼從舊風格改造為新風格的動力。雖然這個過程並不容易——畢竟我們有數十億行現存的代碼——但這種改進確實顯著。」

在標準庫方面,C++23 已經提供了模塊化支持。最重要的是模塊 std,它包含了完整的 std 命名空間:

import std;  // 包含整個標準庫

「這帶來了驚人的改進,」Stroustrup 說,「以十分之一的時間提供十倍的信息——效率提升了 100 倍。這意味著我不用像以前那樣等待編譯時喝那麼多咖啡了。

他特別推薦觀看 Danielle Eckert 在 2022 年 CppCon 上題為《Contemporary C++ in Action》的演講,「這個演講展示了現代 C++ 特性在實際項目中的應用,非常精彩。如果可能,你一定要去看一下這個影片

影片鏈接:https://www.youtube.com/watch?v=yUIFdL3D0Vk

模塊化的概念早在 1994 年的《C++ 語言的設計和演化》中就已提出,」Stroustrup 補充道,「現在我們終於實現了!這個特性不僅讓代碼更清晰,也大大提升了開發效率。

泛型編程與概念

泛型編程(generic programming)是當代 C++ 的關鍵基礎,」Stroustrup 如此介紹道,「這個想法最早可以追溯到 80 年代初。那時我就描述過這個概念,只是當時我以為可以用宏來實現——關於這點我錯了,但對需要泛型編程這一點我是對的。現代 C++ 中的大量泛型編程思想都來自 Alex Stepanov。」

泛型編程為 C++ 帶來了多方面的優勢:代碼更加簡潔、思想表達更直觀、實現零開銷抽像、保證類型安全。它在標準庫中無處不在:容器和算法、併發、內存管理、I/O、string 和正則表達式等。

Stroustrup 用一個簡單的例子說明了基於概念的泛型編程:

void sort(Sortable_range auto& r);
vector<string> vs;// ... 填充 vs ...sort(vs);
array<int,128> ai;// ... 填充 ai ...sort(ai);
list<int> lsti;// ... 填充 lsti ...sort(lsti);  // 編譯錯誤:list 不支持隨機訪問

「這段代碼展示了幾個隱含的要求,」他解釋道,「容器的類型、元素的類型、元素的數量、比較準則等。概念(concept)的作用就是明確指定對類型 r 的要求。當編譯器看到 vector 時,它會問:‘這個 vector 有支持隨機訪問的元素序列嗎? ’ 是的,有。 ‘這些元素是可以比較的嗎?’ 是的。所以代碼可以工作。但對於 list,因為它不支持隨機訪問,編譯器會立即發現這個錯誤。」

Stroustrup 特別指出,「概念不等同於 ‘類型的類型概念是可以作用於多個類型的謂詞。有些概念還可以接受值參數,可以混合類型和值。但概念本質上是函數,而不是像其他語言中那樣僅僅是函數簽名的集合。

隨後,他進一步解釋了為什麼 list 不支持隨機訪問是一個特意的設計:「如果在一個包含 50 萬個元素的 list 中使用下標訪問,會非常非常慢。所以這種限制實際上是在保護開發者避免寫出性能糟糕的代碼。

更複雜的情況是,許多算法都需要多個模板參數類型,而且這些類型之間往往需要建立某種關係。Stroustrup 展示了一個來自標準庫的例子:

template<ranges::input_range R,         indirect_unary_predicate<iterator_t<R>> Pred>Iterator_t<R> ranges::find_if(R&& r, Pred p);
vector<string> numbers;  // 存儲數字的 string,如 "13" 和 "123.45"// ... 填充 numbers ...auto q = find_if(numbers,     [](const string& s) { return stoi(s) < 42; });  // lambda 表達式

「這裏的概念實際上是編譯期謂詞(compile-time predicate,它們在編譯期執行並返回布爾值。通常一個概念會基於其他概念構建,形成一個完整的類型約束體系。」

Stroustrup 表示,概念並不是什麼新鮮事物:「每個成功的泛型庫都包含某種形式的概念。它們存在於設計者的構思中,記錄於技術文檔中,體現在代碼註釋中。比如 C/C++ 的內置類型概念(算術類型和浮點類型)、STL 中的迭代器、序列和容器概念、數學概念(單子、群、環、域)、圖論概念(邊、頂點、圖、有向無環圖等)……」

講到此處,Stroustrup 致敬了 C 語言之父丹尼斯·里奇(Dennis Ritchie, 1941-2011):

實際上,我們只是為這些概念提供了語言層面的表示方法,讓編譯器能夠理解和檢查它們。這要求我們學會有效運用這種語言支持。」他說道,「編譯期編程(compile-time programming在當今的 C++ 中非常基礎,這種技術也已經存在很長時間了。有趣的是,在 2010 年時,還有人斷言編譯時求值不僅毫無用處,而且根本無法實現。現在的發展已經證明,他們的判斷完全錯了。」

「使用概念還帶來了許多實際好處:支持更好的程序設計,提升代碼可讀性和可維護性,避免過度使用無約束的 auto 和 typename,大幅改進錯誤信息。」他打了個比方:「還記得那個只有內置類型沒有類(class)的年代嗎?C++ 從未有過這種時期,但現在的 C 語言仍是這樣。好在 C 現在也有了函數原型。

「概念的引入還極大地簡化了條件約束的表達。」Stroustrup 展示了一個例子:

template<typename T> class Ptr {    // ...    T* operator->() requires is_class<T>;  // 僅當 T 是類時才提供 -> 運算符};
template<typename T, typename U> class Pair {    // ...    template<convertible<T> 湯臣, convertible<U> UU>    Pair(const 湯臣&, const UU&);  // 只為可轉換為成員的類型提供構造函數};

傳統的 enable_if 方案原始、醜陋、非通用,且容易出錯,」他最終評價道,「而使用概念,我們可以用更簡潔、更直觀的方式表達這些約束。

協程:狀態保持!

「說到協程(coroutine),這其實是個有趣的故事,」Stroustrup 回憶道,「在 C++ 發展的最初十年,協程是我們的一個重要優勢。但後來一些公司因為它不適合他們的機器架構而反對,結果我們失去了這個特性。現在,我們終於把它找回來了。

協程的特點是能在多次調用之間保持其狀態。Stroustrup 用一個生成斐波那契數列的例子來說明:

generator<int> fibonacci()  // 生成 0,1,1,2,3,5,8,13 ...{    int a = 0;  // 初始值    int b = 1;    while (true) {        int next = a + b;        co_yield a;  // 返回當前斐波那契數        a = b;       // 更新狀態        b = next;    }}
for (auto v: fibonacci())    cout << v << '\n';

「這裏的妙處在於狀態的保持,」他解釋道,「我們有計算的狀態——a、b 和 next——它就這樣不斷地計算下一個斐波那契數。協程已經被嵌入到迭代器系統中,所以我們可以用簡單的 for 循環來獲取數列中的值。」

但這個例子還有一個小問題:「這是個無限序列,顯然會帶來問題,我們會遇到溢出。那麼如何限制它只生成特定數量的值呢?」Stroustrup 展示了改進的版本

template<int N>generator<int> fibonacci()  // 生成前 N 個斐波那契數{    int a = 0;    int b = 1;    int count = 0;    while (count < N) {        int next = a + b;        co_yield a;        a = b;        b = next;        count++;    }}
for (auto v: fibonacci<10>())  // 只生成十個數:0,1,1,2,3,5,8,13,21,34    cout << v << '\n';

「雖然標準庫對協程的支持還不如我想要的那麼完善,」Stroustrup 說,「但這個例子中使用的 generator 已經在 C++23 中可用了。如果你使用的是較早的編譯器,還可以使用 Facebook 的 coro 庫或其他任務庫。這個例子很好地展示了模板和協程是如何和諧地協同工作的。」

「協程為我們提供了一種漂亮的方式來處理需要保持狀態的計算,」他總結道。「它讓代碼更容易理解,也更容易維護。這正是我們一直追求的目標:簡單的事情簡單做。

調優:「洋蔥原則」

「對某些代碼來說,調優是必要的,」Stroustrup 轉入了性能優化的話題。「但我們都聽過 ‘避免過早優化’ 這個建議。重要的是要在優化前後都進行性能測量,同時在設計接口時就要考慮優化空間。」

他提出了幾個關鍵原則:

1. 接口設計需明確定義

2. 保持類型信息的完整性

3. 提供足夠信息支持檢查和優化

4. 管理複雜度:”簡單的事情簡單做!”

我把這個叫做 ‘洋蔥原則’,」Stroustrup 打了個生動的比方,「可以把代碼想像成洋蔥的層。每當我們需要優化或處理特殊情況,我們就可能需要剝掉一層抽像。但要記住,每剝掉一層,你就會哭得更厲害。

「為什麼會這樣?」他繼續解釋道,「因為每深入一層,你就有可能遇到更多的錯誤,必須寫更多的代碼,代碼也更難理解。所以在真正需要之前,不要輕易剝掉一層抽像。這就是我對 ‘不要過早優化’ 的理解。」

此外,關於併發(concurrency),Stroustrup 指出這是一個需要單獨討論的重要話題。「你需要它來提高效率。在標準庫中有廣泛的、相當低層的併發支持:線程和鎖、共享機制、並行算法、協作取消、Future 機制、協程等等。這些都是為了性能,但同時也帶來了複雜性。」

指南和規格配置:走向未來

不要停留在 20 世紀,」演講走進尾聲時,Stroustrup 直截了當地說,「但這說起來容易做起來難。大多數代碼都包含一些舊的部分,升級這些代碼既困難又耗時。雖然升級能帶來巨大好處——比如引入模塊能顯著提升編譯速度——但要摒棄次優技術確實很難,因為我們不僅要面對海量的歷史代碼,還要克服根深蒂固的編程習慣。」

我們面臨一個根本性的問題,我們不能改變語言本身——穩定性和兼容性是 C++ 的核心優勢。但我們可以改變使用語言的方式。

為了說明這一點,Stroustrup 分享了一個有趣的觀察:「大約每兩週,我都會收到一個有趣的請求。這個請求總是包含三個部分:首先是跟我說 ‘C++ 太複雜了,必須簡化’——我同意,確實如此——但緊接著又跟我說 ‘順便提一下,我們絕對需要增加這兩個新特性’。而且還要保證 ‘別破壞我的代碼,我可是有上百萬行呢’。這三件事是沒法同時做到的。

「正是基於這種現實,」他繼續說,「我們採取了一種務實的策略:通過一套靈活的指南規則體系來簡化語言的使用,而不是改變語言本身。這些指南可以根據項目需求選擇性採納。比如 C++ Core Guidelines 就是一個很好的例子,而且已經有了實踐工具的支持,如 Visual Studio、GCC 和 Clang-Tidy 都能幫助執行這些指南——這不是科幻小說,這些工具現在就可以使用。」

在標準委員會中,Stroustrup 和同事們正在推進一個更進一步的方案:規格配置(profile)每個規格配置是一套強製性的指南規則,」他解釋道「雖然現在還在製定中,但其目標很明確:讓開發者能夠根據需要選擇不同類型的安全性級別和執行強度。這將幫助我們在保持語言強大的同時,使其更容易正確使用。」

Stroustrup 建議的初始規格配置包括:

1. 算法:全面的範圍檢查,禁止解引用 end() 迭代器;

2. 算術:檢測上溢和下溢;

3. 類型轉換:全部禁用;

4. 併發:消除死鎖和數據競爭(這是個難點);

5. 初始化:所有對象必須初始化;

6. 失效:禁止通過已失效的指針訪問(包括懸空指針);

7. 指針:禁止對內置指針使用下標操作(應使用 span、vector、string 等);

8. 範圍:捕獲範圍錯誤;

9. RAII:所有資源必須由句柄管理;

10. 類型:涵蓋初始化、範圍、轉換、失效和指針規則;

11. 聯合體:禁止使用 union(應使用 variant 等);

他說:「我們需要那些底層的、複雜的、接近硬件的、容易出錯的、專家級的特性,因為它們是高效實現高層功能的基礎。很多底層特性在正確使用時都很有價值。但一旦我們有了這些基礎,就可以在此之上建立更安全、更簡單的編程模型。」

我們想要的是「增強版 C++」——簡單、安全、靈活、高效,而不是功能受限的子集。我們不能失去 C++ 最重要的特性:高性能和對硬件的直接控制。而且這些改進不會改變語言的本質,最終的代碼仍然是符合 ISO C++ 標準的。」

Stroustrup 還總結了 C++ 的編程模型:

  • 靜態類型系統,同時支持內置類型和用戶定義類型

  • 支持值語義和引用語義

  • 統一的資源管理機制(RAII)

  • 高效的面向對象編程

  • 靈活且高效的泛型編程

  • 編譯期編程

  • 直接訪問硬件和操作系統

  • 通過庫實現的併發支持(借助內部指令)

  • 最終淘汰 C 預處理器

在演講的最後,Stroustrup 展示了一張 C++ 用戶數量增長的圖表。

「C++ 在設計之初就考慮到語言會不斷演進,」他說,「從 1979 年的 C with Classes,到 1998 年引入異常、模板和命名空間,再到 2011 年增加併發、lambda 表達式和智能指針,直到 2020 年帶來概念、協程、模塊等特性,C++ 一直在成長。」

我從一開始就知道,我不可能獨自在合理的時間內構建出我想要的完整語言,」他坦言道。「所以 C++ 在不斷演進,現在有了很多真正有用的新特性。但關鍵是,我們要活在曲線的上方,使用當代 C++ 中可用的工具,而不是停留在最古老的部分。因為歸根到底——編程語言的價值體現在其應用程序的質量之中。

在 C++ 之父 Bjarne Stroustrup 的主題演講《重新認識 C++:跨世紀的現代演進》中,他系統地探討了資源管理、錯誤處理、模塊化、泛型編程等 C++ 的核心特性,並詳細闡述了他對 C++ 未來發展的願景。而在同場的爐邊談話環節中,Bjarne Stroustrup 不僅分享了對當前 C++ 發展現狀的思考,也表達了對未來的期待。

想要第一時間深入瞭解 C++ 之父的觀點,或重溫他對 C++  技術演進的精彩論述?為了幫助開發者更好地理解和運用現代 C++,CSDN 聯合 Boolan 特別策劃了「C++ 名家系列直播活動」。全球頂尖的 C++ 專家,將為參與者深入解析現代 C++ 的核心理念和實踐經驗。更重要的是,我們還將向參與者獨家贈送《現代 C++ 白皮書》中文版。這份白皮書凝聚了 C++ 之父 Stroustrup 15 年來的技術思考,以及全球 C++ 專家群體的智慧結晶,堪稱現代 C++ 開發者的必讀指南。