C++作為一門經典的編程語言,從上世紀八十年代起至今一直被廣泛應用在系統開發和高性能計算領域。近幾年來隨著各種編程語言和范式的興起,C++的身影漸漸淡出了人們的視野。但是作為一個仍在不斷進步的語言,C++在最近幾年飛速發展,已經具備了現代語言應有的特性,而且也有了許多已有的和正在進行的新的拓展。
經典的C++
作為C語言的超集,一方面,C++集成了C在系統編程優點,能夠精確的控制內存中的每一個bit;另一方面,提供了豐富的抽象機制和編程范式,引入了面向對象、泛型編程和函數式編程等風格。因為這一點,C++擁有了與C媲美的運行時性能,另一方面,也簡化了C語言帶來的領域建模的難度。但是因為C++的整體設計結合了多種風格,幾乎相當於嵌套了幾個小語言的一個龐大的系統,這也使得C++的整體易學性和易用性上有些差勁。同時,由於標准庫更新跟不上需求,在諸如Concurrency/Network等應用層的軟件設計方面逐漸被Java等後來者取代。而且,各個C++廠商對編譯器的實現並沒有完全參考ISO標准,也造成了很多跨平台可移植性和兼容性問題。
現代C++
C++在最近幾年進行了幾次探索和蛻變,讓整個語言變得更具備現代化的特色。
資源管理
RAII(Resource Aquiration is Initialization,資源獲取即初始化)作為C++的特色之一,被廣泛地應用到C++的程序中。RAII通過堆對象的生命周期來控制資源(包括堆內存、文件句柄、網絡連接等)的生命周期,使得資源管理變得更加自動化,同時也避免了引入垃圾回收帶來的運行時負擔。但這種模式有一個很重要的問題,就是當需要對資源進行共享時,需要做更多額外的工作來進行檢查和同步等工作。
作為更現代的資源管理方式,C++11中引入了兩種智能指針,std::shared_ptr和std::unique_ptr。前者擁有線程安全的引用計數,後者則是通過所有權(owenrship)轉移來控制資源的生存周期。C++11中也引入了右值引用和移動語義,來避免資源傳遞的過程中的不必要的復制。
與Rust中的生命周期(Lifetime)和所有權(Ownership)的概念類似,C++的std::unique_ptr在每一次值傳遞的時候將自身持有的資源轉移到賦值的目標,同時結合移動語義,將賦值過程進一步地優化。
Lambda
Functor作為C++ STL的一個重要組件,也是C++中被使用很多的一個功能。一個Functor其實就是一個重載了operator()的類的實例對象,這種對象配合C++模版的行為,可以被簡單看成一個函數來調用,所以被稱為Functor(函子)。但是,由於C++對於匿名類和內部類支持並不夠好,使用Functor必須提前進行設計。一方面不方便使用,另一方面,定義和使用分離,對代碼的組織和理解也造成了一定的困難。
首先,lambda作為Functor的替代品,解決了不能即時定義並使用的問題。配合STL中的容器和算法,lambda也能將C++的函數式風格發揮到極致。其次,出於C++一貫對性能和抽象的考慮,引入了lambda capture的概念,使得對象的生命周期能夠綁定到lambda表達式,也就能夠構建出閉包對象(closure)。另外,C++14中加入的generic lambda,增強了lambda的類型推導算法,在不損失類型安全特性的基礎上,讓組合式編程(Combinator–based Programming)更加易於實現。
並發
在C++設計的初期,並發並未作為核心的語言特性考慮在內。並且,線程等並發模型在不同平台之上也有各種不同的實現,構建一個統一的並發模型也很困難。
C++11中重新設計了C++的內存模型,在保持原有兼容性的基礎之上加入了並發的內容。同時標准庫中也加入了線程(<thread>)、信號量(<condition_variable>)、互斥鎖(<mutex>)和原子操作(<atomic>)等內容。同時也在此基礎上封裝了future/promise模式和async等操作。
元編程
C++自身對元編程提供了良好的支持。作為主要組件之一的模版,提供了編譯時的數值計算和類型計算。但一方面由於使用模版減慢編譯速度,另一方面,在使用模版的時候,非常難以調試和排錯,這讓很多人望而卻步,甚至對基於模版的STL組件也有一種畏懼感。
C++11中對元編程支持做了加強。首先是把type traits作為標准庫引入,能夠給模版提供一套直觀的約束,也讓類型作為C++中的第一類值(first-class value)存在;另外constexpr的引入簡化了編譯時的值運算,配合用戶自定義字面量(user-defined literals)以及可變參數模版(varadic template/parameter pack)等特性,讓C++能夠更方便地定義內部DSL。
Bright Future
作為一門經典的編程語言,C++至今還在不斷地更新著。即將到來的C++17中,正在籌備著這些重要的特性:
-更豐富的標准庫:C++中對File System、Network等重要的組件進行了標准化的支持,
-Module TS:模塊化提案,用於替代繼承自C語言的頭文件,簡化C++的編譯模型和模塊依賴,
-Concepts TS:用於增強類型約束和類型推導,同時也簡化模版的用法,
-Reflection TS:提供編譯期靜態反射的支持,簡化和增強type traits,提供更豐富的元編程功能。
Conclusion
可以看到C++發展至今一直都走在時代的前列線上。一方面,增加了更多適合應用和系統開發的組件,另一方面,通過語言特性的擴充來簡化抽象復雜度。作為這樣一個兼具新生特性和歷史責任的編程語言,足以預見其應用的廣度;同樣,更多的系統級開源項目,像Mesos等,也選擇C++作為主要的編程語言。有足夠的理由讓我們相信,C++正在重獲新生。