目錄
?編輯C++ 的發展總結:?編輯
1.?C++ 的早期發展(1979-1985)
2.?C++ 標準化過程(1985-1998)
3.?C++ 標準演化(2003-2011)
4.?C++11(2011年)
5.?C++14(2014年)
6.?C++17(2017年)
7.?C++20(2020年)
8.?C++23(2023年)
1.?C++ 1985: C++ 1.0
主要特性:
示例代碼:
代碼講解:
C++ 1.0 的局限性:
總結:
2.?C++ 1989: C++ 2.0
主要特性:
多重繼承與虛繼承
示例代碼:
代碼講解:
運行輸出:
解釋:
C++ 2.0 的局限性:
總結:
3.?C++ 1990: C++ 3.0
主要特性:
模板的引入
示例代碼:模板示例
代碼講解:
運行輸出:
代碼解釋:
模板的優勢:
C++ 3.0 的局限性:
總結:
4.?C++ 1998: C++98
主要特性:
示例代碼:C++98 的常見特性
代碼講解:
運行輸出:
代碼解釋:
C++98 的局限性:
總結:
5.?C++ 2003: C++03
主要特性和變化:
C++03 與 C++98 的區別:
示例代碼:C++98 和 C++03 的差異
示例代碼:模板特化修復和?SFINAE?改進
代碼解釋:
運行輸出:
C++03 與 C++98 的局限性:
總結:
6.?C++ 2011: C++11
主要新特性:
示例代碼:C++11 特性
代碼解釋:
運行輸出:
C++11 的優勢:
C++11 的局限性:
總結:
7.?C++ 2014: C++14
主要新特性:
示例代碼:C++14 新特性
代碼解釋:
運行輸出:
C++14 的優勢:
C++14 的局限性:
總結:
8.?C++ 2017: C++17
1.?結構化綁定聲明 (Structured Bindings)
示例:
2.?if/else語句中的初始化語句 (If/else with initialization)
示例:
3.?std::optional
示例:
4.?std::string_view
示例:
5.?std::filesystem
示例:
6.?并行算法 (Parallel Algorithms)
示例:
7.?內聯變量 (Inline Variables)
示例:
8.?改進的constexpr
示例:
總結
9.?C++ 2020: C++20
1.?概念 (Concepts)
示例:
2.?范圍 (Ranges)
示例:
3.?協程 (Coroutines)
示例:
4.?三向比較 (Spaceship Operator?<=>)
示例:
5.?模塊 (Modules)
示例:
6.?范圍循環 (Range-based for loop with initializer)
示例:
7.?std::span
示例:
8.?consteval?和?constinit
示例:
總結
10.?C++ 2023: C++23
1.?改進的常量表達式(constexpr)
示例:
2.?std::expected
示例:
3.?范圍(Ranges)庫增強
示例:
4.?std::format?改進
示例:
5.?explicit?改進
示例:
6.?std::span?支持的改進
示例:
7.?新的屬性([[likely]]?和?[[unlikely]])
示例:
總結
?編輯
C++ 的發展總結:
C++ 是由?Bjarne Stroustrup?于 1979 年在貝爾實驗室(Bell Labs)開始開發的,最初是作為 C 語言的一個擴展,目的是在不喪失 C 語言高效性的基礎上,提供面向對象編程的特性。C++ 的發展歷程可以分為以下幾個重要階段:
C++ 的早期發展 | 1979-1985 |
C++ 標準化過程 | 1985-1998 |
C++ 標準演化 | 2003-2011 |
C++11 | 2011年 |
C++14 | 2014年 |
C++17 | 2017年 |
C++20 | 2020年 |
C++23 | 2023年 |
1.?C++ 的早期發展(1979-1985)
- 1979年:C++ 的前身?"C with Classes"?出現。Bjarne Stroustrup 在貝爾實驗室的工作中,設計了一個擴展 C 語言的工具,該工具為 C 語言增加了類(class)、構造函數和析構函數等面向對象特性。它的設計目標是提高程序的可重用性,并通過封裝數據和方法的方式增強程序結構。
- 1983年:C with Classes 更名為 **C++**,并發布了第一版 C++ 語言,開始引入類、繼承、多態等面向對象的特性,雖然這些特性并不完善,但已經為后來的發展奠定了基礎。
- 1985年:C++ 語言的第一個標準版本發布。Stroustrup 為此編寫了《C++ Programming Language》一書,詳細介紹了 C++ 的語法、特性和編程模型。
2.?C++ 標準化過程(1985-1998)
- 1989年:C++ 的第一個國際標準草案發布,作為一種較為成熟的語言,逐漸被越來越多的開發者使用。
- 1990年:C++ 被納入國際標準化組織(ISO)的標準化過程。這個過程中,C++ 逐步加入了更多的語言特性,如模板、異常處理、名字空間等。
- 1998年:C++98 標準發布,這是 C++ 語言的第一個正式標準版本。C++98 通過增加模板支持、標準庫(如 STL)和異常處理機制,使得 C++ 語言更加全面和功能強大,成為當時最主流的編程語言之一。
3.?C++ 標準演化(2003-2011)
- 2003年:C++03 標準發布,主要是對 C++98 標準的修正和小幅改進,修復了一些語言特性中的小錯誤,并未引入重大的新特性。
- 2007年:ISO 發布了 C++0x 標準草案,該標準最終演變為 C++11。在 C++0x 的過程中,許多新的特性開始得到提出和采納,如?自動類型推導、右值引用、lambda 表達式、并發編程?等。C++11 的標準化過程歷時多年,經歷了大量的討論和修改。
4.?C++11(2011年)
- 2011年:C++11 正式發布,它是 C++ 語言的一個重大變革,包含了大量的新特性,標志著 C++ 語言進入了一個全新的時代。C++11 的主要特性包括:
- 自動類型推導(
auto
); - 右值引用和移動語義(
&&
、std::move
); - Lambda 表達式;
- 線程支持(
std::thread
); - 智能指針(
std::unique_ptr
、std::shared_ptr
); - 類型推導(
decltype
)等。
- 自動類型推導(
- C++11 的引入極大提升了 C++ 語言的表達力和現代化程度,使得 C++ 編程更具靈活性和高效性。
5.?C++14(2014年)
- 2014年:C++14 發布,相較于 C++11,C++14 更像是一個小規模的優化和修復版本。C++14 主要增強了 C++11 中的特性,如 Lambda 表達式的泛型支持、
std::make_unique
?的引入、decltype(auto)
?的改進等。此外,還修復了一些編譯器和實現中的問題。 - C++14 讓 C++11 中的很多新特性變得更加穩定,增加了可編程性和工具支持。
6.?C++17(2017年)
- 2017年:C++17 發布,這個版本包含了一些有意義的語言特性和標準庫增強。主要特性包括:
- **
std::optional
**:用于表示可能為空的值; - 結構化綁定聲明(
auto [a, b] = tuple;
); if
?和?switch
?中的初始化語句;- **
std::filesystem
**:用于處理文件和目錄的標準庫; - **改進的?
std::string
?和?std::array
**; - 并行算法(
std::for_each
?等支持并行執行)。
- **
- C++17 不僅增強了語言本身的功能,還進一步加強了對現代硬件和多核處理器的支持,增強了性能和并行計算能力。
7.?C++20(2020年)
- 2020年:C++20 發布,是 C++ 語言歷史上一個非常重要的版本,帶來了許多令人興奮的新特性:
- 模塊(Modules):改善頭文件管理,減少編譯時間;
- 三方比較操作符(
<=>
): 用于自動生成比較操作符(比如?==
,?!=
,?<
,?<=
,?>
,?>=
); - 協程(Coroutines):使得異步編程更加簡潔;
- 概念(Concepts):提供更強的類型約束機制,使模板編程更加安全;
- 范圍 for 循環改進:更簡潔的語法和強大的靈活性;
- **
std::span
**:處理數組和內存塊的輕量級對象; - 改進的標準庫:包括?
std::format
、std::ranges
、std::calendar
?等。
- C++20 為 C++ 帶來了大量的現代化特性,并進一步提升了語言的表達能力、性能和并發編程的支持。
8.?C++23(2023年)
- 2023年:C++23 發布,雖然其變化相較于 C++20 比較平穩,但仍然包含了一些重要的改進和修復:
- 新的標準庫功能:例如,
std::expected
、std::generator
?和?std::ranges
?的進一步改進; - 語言增強:對模板和類型推導的改進,增強了語言的靈活性和可讀性;
- 性能優化:進一步增強編譯器對并行、異步和內存管理的支持。
- 新的標準庫功能:例如,
- C++23 標志著 C++ 語言持續向現代化發展,并且對性能和并發編程的支持進一步加強。
-
從面向過程到面向對象:最初的 C++ 語言只是在 C 語言的基礎上增加了類和面向對象的特性,經過多年發展,C++ 在保留 C 語言高效性的同時,也吸收了面向對象、泛型編程和函數式編程的優勢,成為了一門多范式的語言。
-
標準化過程:從 C++98 到 C++11,再到 C++14、C++17 和 C++20,C++ 逐漸成為一種具有廣泛應用的編程語言,每個版本都帶來了一些新的特性和增強,逐步適應現代軟件開發的需求。
-
現代化與性能:C++ 在引入面向對象特性后,也逐步加入了并行計算、內存管理、泛型編程、協程等現代編程特性,使得它在高性能計算、系統開發、游戲開發和金融等領域仍然占有一席之地。
C++ 的發展歷程體現了它強大的靈活性和持久生命力,C++ 不斷演進,始終保持著與時俱進的能力,成為全球使用最廣泛的編程語言之一。
C++ 的發展歷程可以分為多個版本階段,每個版本都帶來了新的語言特性、庫的改進和標準的增強。下面是 C++ 各個版本的主要變化和特性介紹:
1.?C++ 1985: C++ 1.0
- 最初版本:由貝爾實驗室的?Bjarne Stroustrup?在 1980 年代初期開發。
- 主要特點:
- 在 C 語言的基礎上加入了面向對象編程(OOP)特性。
- 支持類、繼承、多態、封裝等面向對象的基本特性。
- 引入了函數和運算符重載。
C++ 1.0?是由?Bjarne Stroustrup?在貝爾實驗室開發的第一版 C++ 編程語言。它是在 C 語言的基礎上加入了面向對象編程(OOP)的特性,因此也被稱為是“C with Classes”(C 帶類)。C++ 1.0 并不是一個標準化的語言版本,而是一個實驗性語言,它為后來的 C++ 標準奠定了基礎。
主要特性:
-
類與對象:C++ 1.0 引入了面向對象編程的核心概念,最初的類和對象支持比較簡單。
- 類是 C++ 中的基本構造,用于封裝數據和功能。
- 對象是類的實例,表示實際的數據和行為。
-
函數和運算符重載:C++ 1.0 支持函數重載和運算符重載,使得程序員可以根據需要定義不同版本的函數或操作符。
-
基本繼承:C++ 1.0 支持從一個類繼承另一個類,使得可以構建更為復雜的類結構。
-
無標準庫:當時的 C++ 語言沒有像現代 C++ 那樣的標準庫。數據結構和算法通常依賴開發者自己編寫。
示例代碼:
C++ 1.0 版本的代碼相對簡單。以下是一個典型的 C++ 1.0 示例,演示了類的定義、對象創建、繼承以及運算符重載。
#include <iostream>
using namespace std;// 定義一個類
class Box {
private:double length; // 長度double breadth; // 寬度double height; // 高度public:// 構造函數Box(double l, double b, double h) {length = l;breadth = b;height = h;}// 計算體積的方法double volume() {return length * breadth * height;}// 運算符重載Box operator+(const Box& b) {// 返回一個新的 Box 對象,體積相加return Box(length + b.length, breadth + b.breadth, height + b.height);}
};// 主函數
int main() {// 創建對象Box box1(3.5, 1.2, 2.0);Box box2(1.0, 2.0, 3.0);// 計算并輸出 box1 的體積cout << "Box1 Volume: " << box1.volume() << endl;// 運算符重載使用示例Box box3 = box1 + box2;cout << "Box3 Volume (box1 + box2): " << box3.volume() << endl;return 0;
}
代碼講解:
- **類?
Box
**:定義了一個包含?length
、breadth
?和?height
?的類,用于表示一個盒子,并且提供了一個計算體積的方法?volume()
。 - 構造函數:用于初始化?
Box
?對象,設置它的長度、寬度和高度。 - 運算符重載:使用?
operator+
?重載運算符?+
,使得兩個?Box
?對象相加時,返回一個新的?Box
?對象,長度、寬度和高度分別相加。 - 在?
main()
?中創建對象:通過構造函數創建了?box1
?和?box2
,并計算它們的體積。在計算?box3
?的體積時,使用了重載的加法運算符。
C++ 1.0 的局限性:
- 缺少模板:當時的 C++ 并不支持模板(泛型編程),模板編程是后來在 C++ 1990 和 1998 標準中引入的。
- 沒有標準庫:沒有現代 C++ 的 STL(標準模板庫),因此沒有常用的容器、算法等功能。
- 繼承的支持較為基礎:C++ 1.0 支持繼承,但還沒有引入多態、虛函數等更高級的特性。
總結:
C++ 1.0 是 C++ 語言的初步版本,它為面向對象編程提供了基礎設施,并通過類、對象、繼承、重載等功能擴展了 C 語言的功能。雖然當時的 C++ 功能較為簡單,但它為后續版本的語言特性打下了基礎,并引領了 C++ 向更強大的方向發展。
2.?C++ 1989: C++ 2.0
- 增強功能:
- 多重繼承:支持多個基類的繼承。
- 虛繼承:解決多重繼承中的“菱形繼承”問題,確保繼承層次中的基類只有一份副本。
- 抽象類:引入了純虛函數(抽象類)的概念,使得類能夠定義接口。
C++ 2.0?是 C++ 語言的第二個重要版本,發布于 1989 年。C++ 2.0 在 C++ 1.0 的基礎上進行了重要的擴展和改進,引入了多個新特性,特別是?多重繼承?和?虛繼承。這些新特性使得 C++ 的面向對象編程能力得到了顯著增強。C++ 2.0 為后來的 C++ 語言標準奠定了許多重要基礎。
主要特性:
- 多重繼承:C++ 2.0 引入了多重繼承的支持,使得一個類可以繼承多個基類,從而可以組合多個類的功能。
- 虛繼承:為了解決多重繼承帶來的“菱形繼承”問題(即一個類通過多個繼承路徑繼承同一個基類),C++ 2.0 引入了?虛繼承?的概念。虛繼承確保通過多個繼承路徑繼承的同一個基類只有一份副本。
- 虛函數:繼續擴展了對面向對象編程的支持,尤其是通過?虛函數?機制,使得 C++ 支持?運行時多態。
- 更強的類型檢查:C++ 2.0 對類型檢查進行了增強,使得語言的類型系統更加嚴格和安全。
多重繼承與虛繼承
C++ 2.0 的最大變化之一就是支持?多重繼承,并且引入了?虛繼承?來解決多重繼承可能引起的問題。在多重繼承中,如果一個類繼承自多個基類,并且這些基類有公共的祖先類,那么在派生類中會有重復的祖先類副本,這時就可能出現問題。虛繼承解決了這一問題,通過確保只有一個祖先類副本,從而避免了數據冗余和潛在的錯誤。
示例代碼:
以下是一個簡單的示例,演示了?多重繼承?和?虛繼承?的概念。
#include <iostream>
using namespace std;// 基類A
class A {
public:A() { cout << "Class A constructor" << endl; }void showA() { cout << "Class A" << endl; }
};// 基類B
class B {
public:B() { cout << "Class B constructor" << endl; }void showB() { cout << "Class B" << endl; }
};// 基類C,虛繼承A
class C : virtual public A {
public:C() { cout << "Class C constructor" << endl; }void showC() { cout << "Class C" << endl; }
};// 派生類D,虛繼承A和B
class D : public C, public B {
public:D() { cout << "Class D constructor" << endl; }void showD() { cout << "Class D" << endl; }
};int main() {// 創建派生類對象DD d;d.showA(); // 來自基類Ad.showB(); // 來自基類Bd.showC(); // 來自基類Cd.showD(); // 來自派生類Dreturn 0;
}
代碼講解:
- 類 A 和 B:
A
?和?B
?是兩個基類,都有自己的構造函數和成員函數。A
?有一個?showA()
?函數,B
?有一個?showB()
?函數。 - 類 C:
C
?類繼承了?A
?類,并使用?virtual
?關鍵字進行?虛繼承。這樣,在?C
?的子類中,如果有多個繼承自?A
?的路徑,它們會共享同一個?A
?類副本,避免了重復數據。 - 類 D:
D
?類從?C
?和?B
?繼承,并且通過虛繼承機制共享了?A
?類的副本。 - 輸出:
- 當?
D
?類的對象被創建時,首先調用?A
、B
?和?C
?的構造函數,再調用?D
?的構造函數。 showA()
、showB()
?和?showC()
?分別調用了從基類繼承的成員函數。
- 當?
運行輸出:
Class A constructor
Class B constructor
Class C constructor
Class D constructor
Class A
Class B
Class C
Class D
解釋:
- 虛繼承:
C
?類通過?virtual public A
?虛繼承了?A
?類,保證了通過?D
?類的繼承關系,A
?類只有一份副本。即使?D
?類是通過?B
?和?C
?兩個路徑繼承?A
,A
?類也只會被構造一次。 - 多重繼承:
D
?類通過多重繼承繼承了?B
?和?C
,因此?D
?類擁有?B
?和?C
?類的功能。
C++ 2.0 的局限性:
- 沒有命名空間:C++ 2.0 并沒有引入命名空間(namespace),因此容易出現命名沖突的問題。
- 沒有模板支持:模板編程(如函數模板和類模板)在 C++ 2.0 中還沒有出現,這一特性是在 C++ 3.0 中引入的。
- 繼承體系較為簡化:雖然支持多重繼承和虛繼承,但對繼承體系的支持仍較為基礎,隨著 C++ 后續版本的發布,繼承和多態的功能會得到更完善的支持。
總結:
C++ 2.0 通過引入?多重繼承?和?虛繼承?大大增強了 C++ 的面向對象能力,使得 C++ 成為一種更強大的編程語言。這些特性讓 C++ 能夠支持更復雜的類層次結構,解決了多重繼承中的一些難題。雖然 C++ 2.0 語言仍然很基礎,但它為 C++ 后續版本的更高級特性,如模板和更復雜的類型系統,奠定了基礎。
3.?C++ 1990: C++ 3.0
- 功能增強:
- 模板:引入了模板(函數模板和類模板),開始支持泛型編程。
- 標準庫:初步支持了標準模板庫(STL)的概念,雖然 STL 直到后來的版本才成為標準。
C++ 3.0?是 C++ 語言的第三個版本,發布于 1990 年。相比于前兩個版本,C++ 3.0 在語言特性和功能上做出了重要的擴展,最為關鍵的就是引入了?模板?的支持,這是 C++ 語言向?泛型編程?過渡的重要一步。模板的引入使得 C++ 支持編寫與類型無關的代碼,從而使得編程變得更加靈活和強大。
主要特性:
-
模板(Templates):
- 函數模板:允許定義可以接受不同類型參數的函數。
- 類模板:允許定義可以接受不同類型參數的類。模板是 C++ 語言中泛型編程的基礎。
-
增強的類型系統:
- 支持更復雜的類型定義和類型推導。
- 改進了類和對象的類型推斷機制。
-
基本的標準庫(STL的雛形):
- 盡管 C++ 3.0 本身并沒有正式定義標準模板庫(STL),但它開始支持類似 STL 的一些容器和算法概念,為未來 STL 的引入奠定了基礎。
-
支持虛函數、運算符重載等特性:
- C++ 3.0 繼續擴展了面向對象編程的支持,增強了對繼承、多態、運算符重載等特性的支持。
模板的引入
C++ 3.0 的核心改進就是引入了模板機制,使得函數和類能夠接受參數類型作為模板參數。這使得 C++ 能夠支持泛型編程,從而能夠編寫類型安全且重用性更高的代碼。
示例代碼:模板示例
以下是一個簡單的示例,展示了如何在 C++ 3.0 中使用?函數模板?和?類模板。
#include <iostream>
using namespace std;// 函數模板:計算兩個數字的最大值
template <typename T>
T getMax(T a, T b) {return (a > b) ? a : b;
}// 類模板:定義一個簡單的容器類
template <typename T>
class Box {
private:T value;
public:Box(T v) : value(v) {}T getValue() { return value; }void setValue(T v) { value = v; }
};int main() {// 使用函數模板int x = 10, y = 20;cout << "Max of x and y: " << getMax(x, y) << endl;double a = 3.14, b = 2.71;cout << "Max of a and b: " << getMax(a, b) << endl;// 使用類模板Box<int> intBox(100);cout << "Box contains: " << intBox.getValue() << endl;intBox.setValue(200);cout << "Updated Box contains: " << intBox.getValue() << endl;Box<double> doubleBox(3.14159);cout << "Box contains: " << doubleBox.getValue() << endl;return 0;
}
代碼講解:
-
**函數模板?
getMax
**:getMax
?是一個函數模板,它接受兩個類型為?T
?的參數,返回它們中的最大值。T
?是一個類型參數,可以是任何數據類型(如?int
、double
?等),當調用模板函數時,編譯器會根據傳入的參數類型推導出?T
?的具體類型。
-
**類模板?
Box
**:Box
?是一個類模板,它有一個類型為?T
?的成員變量?value
。- 構造函數接受一個?
T
?類型的參數來初始化?value
,并提供了?getValue
?和?setValue
?方法來訪問和修改?value
。
運行輸出:
Max of x and y: 20
Max of a and b: 3.14
Box contains: 100
Updated Box contains: 200
Box contains: 3.14159
代碼解釋:
getMax
?函數模板:在?main()
?中,分別使用了?int
?和?double
?類型的參數來調用?getMax
?函數模板。編譯器根據傳入的參數類型推導出?T
?的類型。Box
?類模板:Box<int>
?和?Box<double>
?分別是使用?int
?和?double
?類型的類模板實例化出來的對象。每個?Box
?對象可以存儲不同類型的數據。
模板的優勢:
- 代碼重用:通過模板,函數和類可以支持多種不同的類型,而不需要為每個類型編寫重復的代碼。
- 類型安全:模板在編譯時進行類型檢查,確保類型的正確性,避免了運行時的類型錯誤。
C++ 3.0 的局限性:
- 模板特性較為基礎:C++ 3.0 中的模板機制較為簡單,沒有現代 C++ 中復雜的模板特性,如模板特化、SFINAE(Substitution Failure Is Not An Error)等。
- 標準庫仍然不成熟:盡管模板提供了更多的靈活性,但標準庫并沒有像 C++11 和 C++14 中那樣強大,STL 的概念才剛剛開始萌芽。
總結:
C++ 3.0 是 C++ 語言的一個重要版本,模板的引入是其最大的亮點,標志著 C++ 進入了泛型編程的時代。模板讓 C++ 變得更加靈活,支持更加高效的代碼重用和類型安全的操作。通過函數模板和類模板,C++ 可以在不同類型之間共享代碼,從而極大地提高了開發效率和代碼的可維護性。雖然 C++ 3.0 的模板機制相對簡單,但它為后續的 C++ 標準化進程和更復雜的模板特性奠定了基礎。
4.?C++ 1998: C++98
- C++ 標準化:C++98 是 C++ 的第一個正式標準版本,由?ISO/IEC 14882:1998?定義。
- 主要特性:
- STL(標準模板庫):引入了標準模板庫,包括?
vector
、list
、map
、set
?等容器,及算法(如排序、查找等)。map - C++ Reference? ??set - C++ Reference - 命名空間(namespace):為了避免名稱沖突,引入了命名空間。
- 異常處理:引入了?
try
、catch
、throw
?異常處理機制。 - RTTI(運行時類型信息):引入了?
typeid
?和?dynamic_cast
,允許運行時識別對象的類型。
- STL(標準模板庫):引入了標準模板庫,包括?
C++98?是 C++ 語言的第一個國際標準,正式由 ISO(國際標準化組織)在 1998 年發布。C++98 語言標準繼承了 C++ 3.0 的核心特性,并在此基礎上進行了多個重要的改進和規范化。這個版本的 C++ 為標準庫(STL)提供了規范,并開始支持更多的現代編程特性。
主要特性:
-
模板:
- C++98 中的模板特性得到了進一步的增強,支持函數模板和類模板,并且模板的使用變得更加廣泛。模板參數可以是類、函數、指針等類型。
-
標準模板庫(STL)
sort - C++ Reference
-
異常處理:
- C++98 提供了標準化的異常處理機制,使用?
try
,?catch
,?throw
?語句來處理運行時錯誤。
- C++98 提供了標準化的異常處理機制,使用?
-
命名空間:
- C++98 引入了?命名空間(
namespace
),用于避免名稱沖突,尤其是在大型項目中。
- C++98 引入了?命名空間(
-
虛函數與多態:
- C++98 繼續強化了面向對象編程的支持,特別是對?虛函數?和?多態?的使用。
-
const 和引用:
- C++98 對?
const
?關鍵字和引用進行了嚴格的規范,使得編程更加安全。
- C++98 對?
-
函數指針和類型轉換:
- 提供了對?函數指針?和?類型轉換(如?
static_cast
,?dynamic_cast
?等)的支持,增強了 C++ 的靈活性。
- 提供了對?函數指針?和?類型轉換(如?
-
類成員的類型推導:
- C++98 引入了對類成員類型的推導,允許在某些情況下省略類型聲明。
示例代碼:C++98 的常見特性
以下是一個綜合示例,展示了 C++98 中的幾個核心特性,包括模板、標準庫(STL)、命名空間和異常處理。
vector - C++ Reference
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>namespace MyNamespace {// 模板函數:計算兩個數的最大值template <typename T>T getMax(T a, T b) {return (a > b) ? a : b;}// 使用 STL 容器:vector 和算法void useSTL() {std::vector<int> vec = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};std::sort(vec.begin(), vec.end());std::cout << "Sorted vector: ";for (int num : vec) {std::cout << num << " ";}std::cout << std::endl;}// 異常處理示例void testException() {try {throw std::out_of_range("Index out of range!");} catch (const std::exception& e) {std::cout << "Caught exception: " << e.what() << std::endl;}}
}int main() {// 使用命名空間using namespace MyNamespace;// 使用模板函數int x = 10, y = 20;std::cout << "Max of x and y: " << getMax(x, y) << std::endl;// 使用 STL 容器和算法useSTL();// 測試異常處理testException();return 0;
}
代碼講解:
-
**模板函數?
getMax
**:- 這是一個簡單的模板函數,接受兩個相同類型的參數,并返回它們中的最大值。
typename T
?表示這是一個模板函數,T
?是占位符類型,可以在調用時由編譯器自動推導出。
- 這是一個簡單的模板函數,接受兩個相同類型的參數,并返回它們中的最大值。
-
STL 容器和算法:
- 在?
useSTL
?函數中,使用了?std::vector
?來存儲整數數據,并使用?std::sort
?算法對數據進行了排序。std::vector
?是 C++98 標準庫中的一個動態數組容器,std::sort
?是一個算法函數,用于對容器中的元素進行排序。
- 在?
-
異常處理:
testException
?函數演示了 C++98 的異常處理機制。在這個函數中,拋出了一個?std::out_of_range
?異常,并在?catch
?塊中捕獲它,輸出異常的描述信息。
運行輸出:
Max of x and y: 20
Sorted vector: 1 1 2 3 3 4 5 5 5 6 9
Caught exception: Index out of range!
代碼解釋:
- **模板?
getMax
**:通過模板,可以在運行時自動確定?T
?的類型,支持不同的數據類型(如?int
、double
?等)。在本例中,它比較了兩個整數?x
?和?y
。 - **STL 容器?
std::vector
?和?std::sort
**:std::vector
?是一個可以動態調整大小的容器,它存儲一系列元素。std::sort
?是一個通用算法,用來對容器中的元素進行排序。 - 異常處理:C++98 提供了標準的異常處理機制,允許在代碼運行過程中拋出和捕獲異常,避免程序因錯誤而崩潰。
C++98 的局限性:
- 沒有?
auto
?關鍵字:C++98 中沒有?auto
?關鍵字,因此類型推導只能依靠顯式的類型聲明。 - **沒有?
nullptr
**:C++98 中沒有?nullptr
,指針使用時可能會引發隱式的類型轉換問題。 - 沒有類型推導的?
for
?循環:C++98 中沒有像 C++11 中那樣的基于范圍的?for
?循環(for (auto& elem : container)
)。 - 模板元編程有限:雖然模板功能在 C++98 中已被引入,但對于模板元編程的支持相對有限,模板編程的復雜性和靈活性較低。
總結:
C++98 是 C++ 語言的第一個國際標準版本,它鞏固并標準化了之前 C++3.0 中的許多特性,并加入了?模板?和?STL?等重要特性,使得 C++ 在實際開發中更加高效和靈活。通過模板,C++98 使得代碼可以在不同的數據類型之間重用,同時標準庫(STL)提供了高效的容器和算法支持,大大提高了開發效率。雖然 C++98 為后來的 C++ 標準奠定了基礎,但它在某些領域(如模板編程和自動類型推導)仍存在局限。
5.?C++ 2003: C++03
- 修復和改進:
- 小的改進:C++03 主要是對 C++98 標準的一些修訂和錯誤修正,沒有引入重大新特性。
- 支持一些新的編譯器特性,如增強的模板支持、異常安全性等。
C++03?是 C++ 語言的一個小版本更新,它是對?C++98?的修正版本,主要用于解決一些語言上的不一致性和設計上的小問題。C++03 并未引入許多新的功能,而是對 C++98 標準中的一些細節進行了修正和澄清,確保語言的一致性和規范性。這個版本主要集中在語言規范的完善和一些編譯器支持方面。
C++03 的發布并沒有像 C++98 到 C++11 之間的版本那樣進行革命性的更新,因此它在功能上與 C++98 并無太大差異。主要的更新包括對?模板特化、SFINAE(Substitution Failure Is Not An Error)等方面的細節修正,確保了編譯器能夠更好地支持標準庫。
主要特性和變化:
-
模板的修正和改進:
- C++03 對模板特化和模板元編程做了小的修正,使得編譯器對模板的支持更加一致。
- 改進了模板在某些邊界情況中的行為,避免了 C++98 中一些不一致或令人困惑的部分。
-
標準庫的修正:
- C++03 對標準庫中的一些接口做了微調,解決了 C++98 標準庫中的一些小問題。例如,修復了?
std::vector
?在某些情況下的行為不一致性,確保了 STL 中的算法與容器的更好兼容性。
- C++03 對標準庫中的一些接口做了微調,解決了 C++98 標準庫中的一些小問題。例如,修復了?
-
修復了常見的編譯器問題:
- C++03 對一些編譯器的兼容性問題進行了修復,確保不同廠商的編譯器之間有更好的兼容性。
-
去除了某些不再使用的特性:
- C++03 刪除了一些在 C++98 中冗余或未被廣泛使用的特性,從而使標準更加精簡和一致。
C++03 與 C++98 的區別:
- 細節修正:C++03 主要是針對 C++98 標準中存在的某些歧義性和編譯器實現差異進行修正。它并沒有加入新的語言特性,而是專注于優化語言和標準庫的現有特性。
- STL 和模板的完善:C++03 解決了模板和標準庫的一些小問題,確保標準庫在不同編譯器下的行為一致。
示例代碼:C++98 和 C++03 的差異
由于 C++03 與 C++98 的差異主要體現在語言的細節上,因此以下示例代碼在 C++03 中的表現與 C++98 是相同的。我們展示一些在 C++98 和 C++03 中模板使用的常見問題,這些問題在 C++03 中得到了修正。
示例代碼:模板特化修復和?SFINAE
?改進
#include <iostream>
#include <type_traits>// 模板類的默認實現
template <typename T>
class Printer {
public:static void print(const T& value) {std::cout << value << std::endl;}
};// 特化:對于 const 類型的處理
template <typename T>
class Printer<const T> {
public:static void print(const T& value) {std::cout << "const value: " << value << std::endl;}
};// 使用 SFINAE 來選擇函數
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, void>::type
printType(const T& value) {std::cout << "Non-integer value: " << value << std::endl;
}template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
printType(const T& value) {std::cout << "Integer value: " << value << std::endl;
}int main() {Printer<int>::print(123); // 默認模板Printer<const int>::print(456); // 特化模板printType(123); // 調用整數版本printType(3.14); // 調用非整數版本return 0;
}
代碼解釋:
-
模板類?
Printer
?的特化:Printer
?是一個模板類,在默認情況下,它的?print
?函數打印任意類型的值。- 特化版本?
Printer<const T>
?對?const
?類型的處理進行了特殊化,使其輸出時帶有 "const value: " 字樣。此特化是在 C++03 中明確規定的,確保了特化行為的統一性。
-
SFINAE(Substitution Failure Is Not An Error):
-
printType
?函數使用了 SFINAE 來根據類型?T
?的不同選擇不同的版本。 -
使用?
std::enable_if
?和?std::is_integral
?來判斷?T
?是否為整數類型,并分別調用不同的函數。SFINAE
?機制可以避免無效的模板實例化,確保了代碼的類型安全。 -
如果?
T
?是整數類型,printType(int)
?會被調用;否則,printType(double)
?會被調用。
-
運行輸出:
123
const value: 456
Integer value: 123
Non-integer value: 3.14
C++03 與 C++98 的局限性:
- 沒有新的語言特性:C++03 僅僅是 C++98 的修正版本,沒有引入新的語言特性。開發者并未從中獲得像 C++11、C++14、C++17 那樣的重大進展。
- 標準庫的改進有限:雖然 C++03 修復了一些標準庫的問題,但與后來的 C++ 標準相比,它的功能仍顯得較為簡單。
- 沒有現代化工具:如?
auto
、nullptr
、范圍?for
?循環等特性都沒有出現在 C++03 中,這使得它在一些現代編程需求面前顯得有些過時。
總結:
C++03 是一個對 C++98 的修正版本,主要修復了一些語言規范中的小錯誤和不一致性,改進了模板、STL 和編譯器的兼容性。它并沒有引入新的語言特性,因此在實際使用中,C++98 和 C++03 的差異并不顯著。C++03 主要對 C++98 的一些不明確之處進行了修正,為后續 C++ 標準的進化(如 C++11、C++14)奠定了基礎。對于開發者來說,C++03 更多的是一種穩定性和兼容性更新,而不是一種功能性擴展。
6.?C++ 2011: C++11
- 現代 C++ 的起點:C++11 是 C++ 的一次重大更新,被廣泛認為是 C++ 語言的“現代化”轉折點。
- 關鍵特性:
- 自動類型推斷(
auto
):使用?auto
?關鍵字可以讓編譯器推斷變量類型。- 智能指針:引入了?
std::unique_ptr
、std::shared_ptr
、std::weak_ptr
,用于自動管理內存,避免內存泄漏。- Lambda 表達式:允許定義匿名函數,可以在代碼中更方便地使用函數對象。
- 并發支持:引入了?
<thread>
?庫,允許多線程編程。- **
nullptr
**:引入了?nullptr
?關鍵字,替代?NULL
,提高代碼的類型安全。- 右值引用和移動語義:引入右值引用(
&&
)和?std::move
,提高對象傳遞效率,減少不必要的拷貝。- 范圍 for 循環:引入了簡潔的范圍?
for
?循環,簡化容器遍歷。- 類型別名(
using
):引入?using
?關鍵字,簡化類型別名定義。- 變長模板(Variadic Templates):支持可變參數模板,提高模板的靈活性。
C++11?是 C++ 語言的一個重大更新,正式于 2011 年發布。它引入了大量新的特性和改進,使 C++ 語言更現代化、更加高效和易于使用。C++11 標準的推出,極大地擴展了 C++ 的功能,使得 C++ 開發變得更加靈活、簡潔,同時還提升了性能。
主要新特性:
-
自動類型推導(
auto
):auto
?關鍵字允許編譯器根據表達式的類型自動推導變量的類型,減少了類型聲明的冗余,提高了代碼可讀性。
-
右值引用與移動語義(
&&
?和?std::move
):- 引入右值引用(
&&
)和?std::move
,實現了?移動語義。通過移動資源而不是復制,顯著提高了效率,尤其在需要大量數據傳輸的場合(如容器操作)。
- 引入右值引用(
-
范圍?
for
?循環:- 引入了范圍?
for
?循環(range-based for loop),簡化了容器元素的遍歷,避免了傳統迭代器的復雜性。
- 引入了范圍?
-
Lambda 表達式:
- Lambda 表達式允許在函數內定義匿名函數,并且可以捕獲外部變量,極大地增強了函數式編程的支持。
-
**
nullptr
**:nullptr
?替代了?NULL
,它是一個類型安全的空指針常量,消除了?NULL
?的類型不匹配問題。
-
**
constexpr
**:constexpr
?使得可以在編譯時求值的常量表達式更加簡潔,增強了編譯期計算的能力。
-
并發編程:
<thread>
?庫:- C++11 引入了原生的線程支持,
<thread>
?庫使得多線程編程變得更加容易和高效。
- C++11 引入了原生的線程支持,
-
類型別名(
using
):using
?關鍵字可以用來為類型定義別名,取代了傳統的?typedef
,語法更加簡潔。
-
強類型枚舉(
enum class
):- 引入了強類型枚舉?
enum class
,避免了傳統枚舉可能產生的隱式轉換和命名沖突問題。
- 引入了強類型枚舉?
-
**新標準庫:
std::chrono
**:- C++11 引入了用于處理時間和日期的新標準庫?
std::chrono
,使得處理時間變得更加直觀和精確。
- C++11 引入了用于處理時間和日期的新標準庫?
示例代碼:C++11 特性
下面的代碼示例展示了 C++11 的一些關鍵特性。
#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>
#include <functional>// 1. 自動類型推導
void autoExample() {auto x = 10; // 編譯器自動推導類型為 intauto y = 3.14; // 編譯器自動推導類型為 doublestd::cout << "x: " << x << ", y: " << y << std::endl;
}// 2. 范圍 for 循環
void rangeBasedFor() {std::vector<int> vec = {1, 2, 3, 4, 5};for (auto& num : vec) { // 使用范圍 for 遍歷num *= 2;}std::cout << "Doubled values: ";for (const auto& num : vec) {std::cout << num << " ";}std::cout << std::endl;
}// 3. Lambda 表達式
void lambdaExample() {std::vector<int> vec = {1, 2, 3, 4, 5};int sum = 0;// 使用 lambda 表達式進行求和std::for_each(vec.begin(), vec.end(), [&sum](int num) { sum += num; });std::cout << "Sum of elements: " << sum << std::endl;
}// 4. 移動語義和右值引用
class MyClass {
public:MyClass() { std::cout << "Constructor\n"; }MyClass(const MyClass&) { std::cout << "Copy Constructor\n"; }MyClass(MyClass&&) { std::cout << "Move Constructor\n"; }MyClass& operator=(const MyClass&) { std::cout << "Copy Assignment\n"; return *this; }MyClass& operator=(MyClass&&) { std::cout << "Move Assignment\n"; return *this; }
};void moveExample() {MyClass a;MyClass b = std::move(a); // 使用移動構造函數
}int main() {// 自動類型推導autoExample();// 范圍 for 循環rangeBasedFor();// Lambda 表達式lambdaExample();// 移動語義moveExample();// 使用線程std::thread t([]{ std::cout << "Hello from a thread!\n"; });t.join(); // 等待線程執行完畢return 0;
}
代碼解釋:
-
**自動類型推導 (
auto
)**:- 使用?
auto
?關鍵字,編譯器會自動推導變量?x
?和?y
?的類型,簡化了類型聲明,特別是對于復雜類型(如迭代器和函數返回類型)時非常有用。
- 使用?
-
范圍?
for
?循環:- 使用 C++11 引入的范圍?
for
?循環來遍歷容器。這個語法簡潔、直觀,避免了顯式的迭代器操作。
- 使用 C++11 引入的范圍?
-
Lambda 表達式:
- 使用?
std::for_each
?算法與 lambda 表達式結合,計算容器中所有元素的總和。lambda 表達式?[&sum](int num) { sum += num; }
?捕獲外部變量?sum
?并對容器中的每個元素執行加法操作。
- 使用?
-
右值引用與移動語義:
- 在?
moveExample
?中,通過?std::move
?實現了對象?a
?的移動,將其資源轉移給對象?b
,觸發了移動構造函數而不是拷貝構造函數。
- 在?
-
線程支持:
- 使用 C++11 的?
<thread>
?庫創建和啟動一個線程,并且通過?join()
?等待線程執行完成。std::thread
?簡化了多線程編程。
- 使用 C++11 的?
運行輸出:
x: 10, y: 3.14
Doubled values: 2 4 6 8 10
Sum of elements: 15
Move Constructor
Hello from a thread!
C++11 的優勢:
- 現代化的語法和功能:C++11 引入的眾多新特性大大提升了語言的靈活性和表達力,減少了冗余代碼,使得 C++ 編程更加簡潔、易讀和高效。
- 性能優化:通過右值引用和移動語義,C++11 使得許多數據傳輸和復制操作得以高效地優化,特別是在容器和大型對象的操作中,性能大幅提升。
- 并發支持:C++11 將多線程支持納入語言標準,使得并發編程變得更加容易和可靠,減少了對外部庫的依賴。
C++11 的局限性:
- 學習曲線:盡管 C++11 引入了許多現代化特性,但對一些開發者來說,掌握這些新特性可能需要一定的學習時間。
- 編譯器支持問題:盡管大部分現代編譯器已經完全支持 C++11,但一些舊的編譯器或開發環境可能存在兼容性問題。
總結:
C++11 是 C++ 語言的一次重大更新,帶來了許多新的語言特性和庫支持,使得 C++ 編程變得更加簡潔、強大和高效。無論是在性能優化、現代語法的引入,還是在并發支持等方面,C++11 都大幅提升了語言的可用性和表達能力。
7.?C++ 2014: C++14
- 小幅增強:
constexpr
?的改進:支持更復雜的編譯時常量計算。- 二進制字面量:引入了支持二進制常量字面量。
auto
?的增強:使得?auto
?可以推導更加復雜的類型。- Lambda 表達式的改進:支持更強的捕獲特性(如捕獲?
*this
?引用)。
C++14?是 C++ 語言的一個相對較小的更新版本,于 2014 年發布。C++14 并沒有像 C++11 那樣引入大量的新特性,而是對 C++11 中的一些特性進行了修復、增強和小幅優化。它的目標是提高語言和標準庫的穩定性,改進一些 C++11 的邊界情況,增強編譯器的支持,并提供一些性能上的提升。
主要新特性:
-
泛型 Lambda 表達式:
- C++14 擴展了 C++11 中的 Lambda 表達式,引入了泛型 Lambda,使得 Lambda 可以接受不同類型的參數而不需要顯式地指定類型。
-
變量模板:
- C++14 引入了?變量模板,允許創建像模板函數一樣的模板變量。之前只有函數和類可以是模板,但 C++14 使得變量也可以具有模板特性。
-
Lambda 表達式的返回類型推導:
- 在 C++14 中,Lambda 表達式可以通過?
auto
?關鍵字自動推導返回類型。這避免了在 Lambda 表達式中手動指定返回類型的需要。
- 在 C++14 中,Lambda 表達式可以通過?
-
**
std::make_unique
**:- 引入了?
std::make_unique
,作為?std::make_shared
?的對稱操作,它簡化了對?std::unique_ptr
?的創建,避免了不必要的?new
?運算符。
- 引入了?
-
**
decltype(auto)
**:- 引入了?
decltype(auto)
?作為函數返回類型的推導方式,它可以推導出具有精確類型的返回值,支持返回引用類型的自動推導。
- 引入了?
-
標準庫改進:
- C++14 修復了 C++11 標準庫中的一些問題,并改進了對各種常見編譯器的支持。標準庫中對線程、智能指針、算法等的支持變得更加穩定和高效。
-
二進制字面量:
- C++14 引入了二進制字面量(
0b
?或?0B
)的支持,使得表示二進制數更加直觀。
- C++14 引入了二進制字面量(
-
**
std::exchange
**:- 新增了?
std::exchange
?函數,它可以簡化交換操作,尤其是當你需要交換一個對象并返回其原值時。
- 新增了?
示例代碼:C++14 新特性
以下代碼展示了 C++14 中的一些關鍵特性,包括泛型 Lambda、變量模板、decltype(auto)
、std::make_unique
?等。
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>// 1. 泛型 Lambda 表達式
void genericLambda() {auto sum = [](auto a, auto b) { return a + b; }; // 泛型 Lambdastd::cout << "Sum of 3 and 4.5: " << sum(3, 4.5) << std::endl;
}// 2. 變量模板
template <typename T>
T pi = T(3.14159);void variableTemplate() {std::cout << "Pi as float: " << pi<float> << std::endl;std::cout << "Pi as double: " << pi<double> << std::endl;
}// 3. Lambda 表達式的返回類型推導
void lambdaReturnType() {auto multiply = [](auto a, auto b) { return a * b; };std::cout << "Multiply 4 and 5.5: " << multiply(4, 5.5) << std::endl;
}// 4. 使用 std::make_unique
void makeUnique() {auto ptr = std::make_unique<int[]>(5); // 使用 make_unique 創建動態數組ptr[0] = 10;std::cout << "First element in unique_ptr array: " << ptr[0] << std::endl;
}// 5. 使用 decltype(auto) 推導返回類型
int&& returnRvalue() {int x = 5;return std::move(x); // 返回右值引用
}void decltypeAuto() {decltype(auto) result = returnRvalue();std::cout << "Rvalue returned: " << result << std::endl;
}// 6. 使用 std::exchange
int increment(int& x) {return std::exchange(x, x + 1); // 將 x 的當前值賦給函數并更新 x
}void exchangeExample() {int value = 10;int oldValue = increment(value);std::cout << "Old value: " << oldValue << ", New value: " << value << std::endl;
}int main() {// 泛型 LambdagenericLambda();// 變量模板variableTemplate();// Lambda 返回類型lambdaReturnType();// 使用 make_uniquemakeUnique();// 使用 decltype(auto)decltypeAuto();// 使用 std::exchangeexchangeExample();return 0;
}
代碼解釋:
-
泛型 Lambda 表達式:
- 通過?
auto
?來聲明 Lambda 表達式的參數類型,使得 Lambda 可以接受任意類型的參數。這使得 Lambda 表達式更加靈活,可以應用于多種不同的類型。
- 通過?
-
變量模板:
pi
?是一個模板變量,它接受一個類型參數?T
,并為每個類型提供不同的常量值。在?variableTemplate()
?中,演示了如何使用模板變量來獲取?pi
?的不同類型值。
-
Lambda 返回類型推導:
- 使用?
auto
?關鍵字,Lambda 表達式會自動推導返回類型。在?lambdaReturnType()
?中,返回類型是乘積結果的類型,auto
?會自動推導出其正確類型。
- 使用?
-
**
std::make_unique
**:std::make_unique
?用于創建?std::unique_ptr
,這是一個智能指針,用于管理動態分配的內存。std::make_unique
?是 C++14 引入的,它比直接使用?new
?更加安全和方便。
-
**
decltype(auto)
**:decltype(auto)
?用于推導函數的返回類型,并且支持返回值是引用的情況。在?decltypeAuto()
?中,returnRvalue()
?返回一個右值引用,通過?decltype(auto)
?可以正確地推導出返回類型。
-
**
std::exchange
**:std::exchange
?是 C++14 引入的一個小工具,它用于交換一個變量的值并返回舊值。在?exchangeExample()
?中,std::exchange
?用于交換?value
?的值并返回交換前的值。
運行輸出:
Sum of 3 and 4.5: 7.5
Pi as float: 3.14159
Pi as double: 3.14159
Multiply 4 and 5.5: 22
First element in unique_ptr array: 10
Rvalue returned: 5
Old value: 10, New value: 11
C++14 的優勢:
- 增強的類型推導:通過?
auto
、decltype(auto)
、泛型 Lambda 表達式等新特性,C++14 提供了更加靈活和精簡的編程體驗。 - 更強大的 Lambda 表達式:C++14 使得 Lambda 表達式支持更復雜的類型推導和捕獲方式,提升了函數式編程的能力。
- 內存管理優化:
std::make_unique
?提高了內存管理的安全性和效率,避免了直接使用?new
?時可能出現的資源泄漏問題。 - 簡化的交換操作:
std::exchange
?使得交換操作更加簡潔,尤其是在需要交換并返回原值的場景中。
C++14 的局限性:
- 更新較小:相比 C++11,C++14 的新特性較少,更多的是對 C++11 特性的增強和補充。因此,C++14 的使用場景更多是在已有代碼的優化和小修小補上。
- 編譯器支持:盡管大部分現代編譯器支持 C++14,但早期的編譯器可能對一些新特性的支持不完全,開發者在使用這些特性時需要確認編譯器的兼容性。
總結:
C++14 是 C++ 語言的一個小版本更新,主要通過增強和擴展 C++11 中的特性來提升語言的靈活性、可用性和安全性。它引入了泛型 Lambda、變量模板、std::make_unique
?等重要特性,并修復了 C++11 中的一些邊界問題。C++14 對于已經使用 C++11 的開發者來說是一個重要的改進,但它的變化相對較小,不會像 C++11 那樣對整個語言體系造成顛覆性的影響。
8.?C++ 2017: C++17
- 重要更新:
- 結構化綁定聲明:允許通過?
auto [x, y] = pair
?等語法,直接解構元組或結構體。- **
std::filesystem
**:引入文件系統庫,提供跨平臺的文件系統操作接口。if
?和?switch
?初始化:允許在?if
?或?switch
?語句中直接初始化變量。- 并行算法:STL 中的算法庫支持并行執行,如并行排序。
- **
std::optional
**:提供了一個容器,可以包含一個值或為空,用于避免空指針的使用。- **
std::variant
**:實現了類似于聯合體的類型,但比 C 的?union
?更安全和靈活。- **改進的?
std::any
**:增強了類型安全的通用容器,允許存儲任意類型。
C++17(也被稱為C++ 2017)是C++編程語言的一個重要版本,它在C++11和C++14的基礎上進行了許多改進,增強了語言特性、庫功能以及編譯器支持。C++17的主要亮點包括:
1.?結構化綁定聲明 (Structured Bindings)
C++17 引入了結構化綁定,允許你將一個結構或元組拆分為多個變量,從而讓代碼更加簡潔易讀。
示例:
#include <tuple>
#include <iostream>std::tuple<int, double, std::string> getData() {return {1, 3.14, "Hello, C++17!"};
}int main() {auto [x, y, z] = getData(); // 結構化綁定std::cout << x << ", " << y << ", " << z << std::endl;return 0;
}
輸出:
1, 3.14, Hello, C++17!
2.?if/else語句中的初始化語句 (If/else with initialization)
C++17允許在if
或else
語句中進行變量初始化,避免了冗余的變量聲明。
示例:
#include <iostream>int main() {if (int x = 10; x > 5) {std::cout << "x is greater than 5" << std::endl;} else {std::cout << "x is not greater than 5" << std::endl;}return 0;
}
輸出:
x is greater than 5
注意:x
只在if
或else
的作用域內有效。
3.?std::optional
std::optional
?是一個模板類,用來表示一個可能為空的值。它可以用來避免使用空指針或特殊值來表示無效數據。
示例:
#include <iostream>
#include <optional>std::optional<int> findValue(bool found) {if (found) {return 42;} else {return std::nullopt; // 返回空值}
}int main() {auto value = findValue(true);if (value) {std::cout << "Found value: " << *value << std::endl;} else {std::cout << "Value not found" << std::endl;}return 0;
}
輸出:
Found value: 42
4.?std::string_view
std::string_view
是一個輕量級的字符串視圖,避免了復制字符串數據,提供了對字符串的只讀訪問。
示例:
#include <iostream>
#include <string_view>void printString(std::string_view str) {std::cout << str << std::endl;
}int main() {std::string str = "Hello, C++17!";printString(str); // 不會復制數據return 0;
}
輸出:
Hello, C++17!
5.?std::filesystem
C++17加入了對文件系統操作的標準庫支持,std::filesystem
使得處理文件和目錄變得更加方便。
示例:
<iostream> - C++ Reference
#include <iostream>
#include <filesystem>namespace fs = std::filesystem;int main() {fs::path p = "example.txt";if (fs::exists(p)) {std::cout << p << " exists!" << std::endl;} else {std::cout << p << " does not exist." << std::endl;}return 0;
}
輸出:
example.txt does not exist.
6.?并行算法 (Parallel Algorithms)
C++17添加了對并行執行算法的支持,例如使用?std::for_each
?和其他標準算法的并行執行。
示例:
#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>int main() {std::vector<int> data = {1, 2, 3, 4, 5, 6, 7, 8, 9};std::for_each(std::execution::par, data.begin(), data.end(), [](int& x) {x *= 2;});for (int x : data) {std::cout << x << " ";}return 0;
}
輸出:
2 4 6 8 10 12 14 16 18
(注意:并行執行可能因環境不同而產生不同的輸出順序)
7.?內聯變量 (Inline Variables)
C++17引入了內聯變量,解決了頭文件中靜態變量帶來的鏈接問題。
示例:
#include <iostream>inline int x = 42; // 內聯變量int main() {std::cout << x << std::endl;return 0;
}
8.?改進的constexpr
C++17擴展了constexpr
的功能,允許在編譯時執行更多的操作,比如動態分配內存和使用if
語句。
示例:
#include <iostream>constexpr int factorial(int n) {return (n == 0) ? 1 : n * factorial(n - 1);
}int main() {std::cout << "Factorial of 5: " << factorial(5) << std::endl;return 0;
}
輸出:
Factorial of 5: 120
總結
C++17引入了許多新特性,極大提高了語言的表達力和編程效率,尤其是在簡化代碼、提高性能和增加靈活性方面。對于現代C++開發者來說,熟練掌握這些特性將大大提升開發體驗和代碼質量。
9.?C++ 2020: C++20
- 重大的新特性:
- 模塊(Modules):引入了模塊化的支持,替代傳統的頭文件和源文件方式,減少編譯時間。
- 協程(Coroutines):支持異步編程,簡化了異步函數的編寫。
- 概念(Concepts):引入了模板約束,使得模板編程更加靈活和易于理解。
- 范圍(Ranges):增強了容器操作的靈活性和簡潔性,提供了更強大的算法支持。
- **
std::format
**:提供了類似 Python 中的格式化字符串功能,簡化了輸出。- **
consteval
?和?constinit
**:新關鍵字,用于常量表達式和常量初始化的嚴格控制。- **改進的?
constexpr
**:支持更多的編譯時功能,包括動態內存分配。
C++20 是 C++ 標準的一個重要更新,它在語言特性、庫功能、并發支持等方面進行了大量的擴展和增強。C++20 對語言進行了重要的現代化,使得 C++ 更加高效、簡潔、易用。以下是 C++20 中的一些主要特性及其代碼示例:
1.?概念 (Concepts)
概念是 C++20 的一項新特性,用來約束模板類型。它允許我們更精確地控制模板參數類型,提供編譯時檢查和更好的錯誤信息。
示例:
#include <iostream>
#include <concepts>template <typename T>
concept Incrementable = requires(T a) { ++a; a++; };template <Incrementable T>
T increment(T x) {return ++x;
}int main() {int a = 5;std::cout << increment(a) << std::endl; // 正常工作// std::string s = "Hello";// std::cout << increment(s) << std::endl; // 編譯錯誤,因為 std::string 不符合 Incrementable 概念return 0;
}
輸出:
6
2.?范圍 (Ranges)
C++20 引入了?std::ranges
,為標準庫中的容器和算法提供了更加一致和方便的操作方法,支持通過管道操作符(|
)組合算法。
示例:
#include <iostream>
#include <vector>
#include <ranges>int main() {std::vector<int> nums = {1, 2, 3, 4, 5};// 使用管道操作符對容器進行操作auto result = nums | std::views::transform([](int x) { return x * 2; })| std::views::filter([](int x) { return x > 5; });for (int val : result) {std::cout << val << " ";}return 0;
}
輸出:
6 8 10
3.?協程 (Coroutines)
C++20 引入了協程支持,使得編寫異步代碼更加簡潔。協程允許暫停和恢復函數的執行,適用于處理 I/O 操作或其他需要異步操作的場景。
示例:
#include <iostream>
#include <coroutine>struct Task {struct promise_type;using handle_type = std::coroutine_handle<promise_type>;struct promise_type {Task get_return_object() { return Task{handle_type::from_promise(*this)}; }std::suspend_always initial_suspend() { return {}; }std::suspend_always final_suspend() noexcept { return {}; }void unhandled_exception() { std::exit(1); }void return_void() {}};handle_type coro;Task(handle_type h) : coro(h) {}~Task() { coro.destroy(); }void resume() { coro.resume(); }
};Task simpleCoroutine() {std::cout << "Start of coroutine\n";co_await std::suspend_always{};std::cout << "End of coroutine\n";
}int main() {auto coro = simpleCoroutine();coro.resume(); // 啟動協程coro.resume(); // 恢復協程return 0;
}
輸出:
Start of coroutine
End of coroutine
4.?三向比較 (Spaceship Operator?<=>
)
C++20 引入了“太空船操作符” (<=>
),也叫做三向比較操作符,它提供了一種簡化的方式來執行比較操作,如?<
、<=
、==
、>
、>=
。
示例:
#include <iostream>struct Point {int x, y;auto operator<=>(const Point&) const = default; // 默認生成比較操作符
};int main() {Point p1 = {1, 2}, p2 = {2, 3};if (p1 < p2) {std::cout << "p1 is less than p2\n";}return 0;
}
輸出:
p1 is less than p2
5.?模塊 (Modules)
C++20 引入了模塊的概念,這是對頭文件的替代。模塊可以提高編譯速度,避免頭文件帶來的重復處理和依賴問題。模塊支持?import
?語句來替代傳統的?#include
。
示例:
假設我們有一個模塊?math
:
// math.cppm - 模塊定義文件
export module math;
export int add(int a, int b) { return a + b; }
然后在主程序中導入該模塊:
// main.cpp
import math;int main() {int result = add(3, 4);std::cout << result << std::endl; // 輸出 7return 0;
}
注意:模塊在許多編譯器中仍處于實驗階段,需要啟用特定的編譯器選項。
6.?范圍循環 (Range-based for loop with initializer)
C++20 增強了范圍 for 循環,允許在循環中初始化變量。
示例:
#include <iostream>
#include <vector>int main() {std::vector<int> nums = {1, 2, 3, 4};for (auto&& [index, value] : nums) { // 使用結構化綁定std::cout << "Value: " << value << std::endl;}return 0;
}
輸出:
Value: 1
Value: 2
Value: 3
Value: 4
7.?std::span
std::span
?是 C++20 新增的一個輕量級的視圖容器,它可以用來表示一個數組的連續區間。它與傳統的指針數組相比,更加安全,并支持對數組進行邊界檢查。
示例:
#include <iostream>
#include <span>void printSpan(std::span<int> sp) {for (auto val : sp) {std::cout << val << " ";}
}int main() {int arr[] = {1, 2, 3, 4, 5};printSpan(arr); // 使用 std::span 傳遞數組return 0;
}
輸出:
1 2 3 4 5
8.?consteval
?和?constinit
C++20 引入了?consteval
?和?constinit
?關鍵字:
consteval
?用于指定一個函數必須在編譯時求值。constinit
?用于確保某個變量在初始化時是常量。
示例:
#include <iostream>consteval int square(int n) { return n * n; }int main() {constexpr int result = square(5); // 在編譯時計算std::cout << result << std::endl; // 輸出 25return 0;
}
輸出:
25
總結
C++20 引入了許多強大的新特性,極大增強了 C++ 的表達能力和編程效率。它使得編寫更現代、更安全和更高效的 C++ 代碼變得更加容易。例如,概念和協程提高了代碼的可讀性和可維護性,而模塊的引入可以顯著提高編譯性能。掌握 C++20 的特性將有助于編寫更清晰、強大和高效的 C++ 代碼。
10.?C++ 2023: C++23
- 新特性和小幅增強:
- **擴展的?
std::ranges
**:提供更多的支持與增強,使得 C++ 的標準庫更具表達力和功能。
- 改進的協程支持:協程功能得到進一步加強,增加了更多的靈活性和優化。
- 更好的標準化和規范:提高了 C++ 語言和標準庫的易用性和性能。
C++23(正式名稱為 C++23)是C++語言的最新標準,作為C++20和C++17之后的下一代標準,C++23在語言特性、庫功能和編譯器優化等方面引入了一些重要的改進。以下是C++23中的一些新特性和代碼示例。
1.?改進的常量表達式(constexpr
)
C++23擴展了constexpr
的功能,允許更多復雜的功能在編譯時執行。例如,C++23允許在constexpr
函數中使用try-catch
語句,這在之前的標準中是無法實現的。
示例:
constexpr int safe_divide(int a, int b) {if (b == 0) throw std::invalid_argument("Division by zero");return a / b;
}int main() {constexpr int result = safe_divide(10, 2); // 編譯時執行return 0;
}
2.?std::expected
C++23引入了std::expected
,它是一個可以用來表示函數調用結果的類型,類似于std::optional
,但是它包含了錯誤信息。這個特性非常適合替代try-catch
塊來進行錯誤處理,尤其是在函數返回時希望包含更多的錯誤信息時。
示例:
#include <expected>
#include <iostream>std::expected<int, std::string> divide(int a, int b) {if (b == 0) {return std::unexpected("Division by zero");}return a / b;
}int main() {auto result = divide(10, 0);if (result) {std::cout << "Result: " << *result << std::endl;} else {std::cout << "Error: " << result.error() << std::endl;}return 0;
}
3.?范圍(Ranges)庫增強
C++20引入了范圍(Ranges)庫,C++23在此基礎上進行了增強。新增了更豐富的算法和視圖,使得在進行集合操作時,代碼更加簡潔且易于理解。
示例:
#include <ranges>
#include <vector>
#include <iostream>int main() {std::vector<int> v = {1, 2, 3, 4, 5};// 使用ranges庫處理集合auto result = v | std::views::transform([](int n) { return n * n; })| std::views::filter([](int n) { return n > 10; });for (int i : result) {std::cout << i << " ";}return 0;
}
4.?std::format
?改進
C++20引入了?std::format
?來格式化字符串,C++23對其進行了進一步改進。新增了更多的格式化選項,以及對各種類型的支持。
示例:
#include <format>
#include <iostream>int main() {int age = 25;std::string name = "Alice";std::string formatted = std::format("Name: {}, Age: {}", name, age);std::cout << formatted << std::endl;return 0;
}
5.?explicit
?改進
C++23擴展了explicit
關鍵字,可以用于更加靈活的構造函數,使其適應更復雜的類型轉換需求。
示例:
struct A {explicit A(int x) {} // 顯式構造函數
};struct B {explicit B(A a) {} // 顯式構造函數
};int main() {A a(1);B b(a); // 需要顯示構造A對象的參數return 0;
}
6.?std::span
?支持的改進
std::span
?是C++20中引入的用于表示數組片段的類,C++23對其進行了擴展,支持了更多的功能。
示例:
#include <span>
#include <iostream>void print_span(std::span<int> s) {for (auto elem : s) {std::cout << elem << " ";}
}int main() {int arr[] = {1, 2, 3, 4, 5};std::span<int> sp(arr, 3); // 只傳遞數組的前3個元素print_span(sp);return 0;
}
7.?新的屬性([[likely]]
?和?[[unlikely]]
)
C++23引入了?[[likely]]
?和?[[unlikely]]
?屬性,用于給編譯器提供分支預測的提示,幫助優化代碼。
示例:
#include <iostream>int main() {bool condition = true;if ([[likely]] condition) {std::cout << "Condition is likely true" << std::endl;} else {std::cout << "Condition is unlikely true" << std::endl;}return 0;
}
總結
C++23增強了語言的表達能力和效率,提供了更多的編程便利性,尤其在常量表達式、錯誤處理、范圍操作、字符串格式化和編譯時優化方面有顯著的提升。這些特性使得C++更加現代化,代碼更加簡潔易懂,同時也帶來了更高效的執行性能。
這些新特性和API增強為開發者提供了更加靈活和強大的工具,可以讓代碼更加高效、易維護并且更具可讀性。