在《C++導(dǎo)學(xué)(第二版)》中,C++的創(chuàng)造者本賈尼?斯特勞斯特魯普描述了現(xiàn)代C++語言的構(gòu)成。這本簡潔、自成體系的導(dǎo)引書籍包含了大多數(shù)主要C++語言特性和主要標(biāo)準(zhǔn)庫組件——當(dāng)然,并未深入介紹,而是給予程序員一個(gè)有意義的語言概述、一些關(guān)鍵的例子以及起步階段的實(shí)用幫助。
教而至簡,不亦樂乎。
——西塞羅
現(xiàn)在的C++感覺就像是一種新的語言。與C++98相比,使用現(xiàn)在的C++我能更清晰、更簡單、更直接地表達(dá)思想。而且,編譯器可以更好地檢查程序中的錯(cuò)誤,程序的運(yùn)行速度也提高了。
本書給出C++語言的一個(gè)概述,這里所說的C++是由當(dāng)前的ISO C++標(biāo)準(zhǔn)C++17定義的,由主要的C++提供商實(shí)現(xiàn)。此外,本書還會介紹一些目前在使用的ISO技術(shù)規(guī)范定義的概念和模塊,但它們在C++20尚無計(jì)劃包含進(jìn)標(biāo)準(zhǔn)中。
就像其他任何一種現(xiàn)代編程語言一樣,C++規(guī)模龐大且提供了非常豐富的庫,這是高效編程所需的。這本小冊子的目的是讓一個(gè)有經(jīng)驗(yàn)的程序員快速了解現(xiàn)代C++語言,因此它覆蓋了C++大多數(shù)主要的語言特性和標(biāo)準(zhǔn)庫組件。讀者花費(fèi)幾個(gè)小時(shí)就能讀完這本書,但顯然要想寫出漂亮的C++程序絕非一日之功。好在本書的目的并非讓讀者熟練掌握一切,而只是給出一個(gè)概覽,給出一些關(guān)鍵的例子,幫助讀者開始自己的C++之旅。
假設(shè)讀者已經(jīng)擁有了一些編程經(jīng)驗(yàn)。如果沒有,建議你先找一本入門教材學(xué)習(xí),比如《Programming: Principles and Practice Using C++,Second Edition》(C++程序設(shè)計(jì)原理與實(shí)踐(第2版))[Stroustrup, 2014],然后再來學(xué)習(xí)本書。即便你曾經(jīng)編寫過程序,你使用的語言或者編寫的應(yīng)用也可能在風(fēng)格或形式上與本書所介紹的C++相距甚遠(yuǎn)。
我們用城市觀光的例子來說明本書的作用,比如游覽哥本哈根或者紐約。在短短幾個(gè)小時(shí)之內(nèi),你可能會匆匆游覽幾個(gè)主要的景點(diǎn),聽一些有趣的傳說或故事,然后聽取建議接下來做什么。僅靠這樣一段旅程,你無法真正了解這座城市,也無法完全理解聽到和看到的東西,更無法熟悉這座城市正式的和非正式的生存法則。畢竟想要真正了解一座城市,你必須生活在其中,而且往往需要多年。不過如果幸運(yùn)的話,此時(shí)你已經(jīng)對城市的概貌有了一些了解,知道了它的某些特殊之處,并且對某些方面產(chǎn)生了興趣。在這段旅程之后,你就可以開始真正的探索了。
本書的風(fēng)格就像這段旅程,它會為你介紹C++語言的主要特性,這是按其所支持的程序設(shè)計(jì)風(fēng)格來呈現(xiàn)的,例如面向?qū)ο缶幊毯头盒途幊。本書不?zhǔn)備提供一個(gè)詳細(xì)的、手冊式的、逐條特性的C++語言描述。遵循優(yōu)秀教科書的傳統(tǒng),我努力在使用每個(gè)語言特性之前對其進(jìn)行解釋,但實(shí)際情況并不總能允許我這樣做,而且并不是每個(gè)人都會嚴(yán)格按順序閱讀本書。因此,我鼓勵讀者使用交叉引用和索引。
類似地,本書以示例的方式介紹標(biāo)準(zhǔn)庫,而非逐一列舉標(biāo)準(zhǔn)庫特性。本書沒有介紹ISO標(biāo)準(zhǔn)之外的庫,讀者需要的話可以查閱相關(guān)資料,例如[Stroustrup, 2013]和[Stroustrup, 2014],網(wǎng)絡(luò)上也有大量(質(zhì)量參差不齊)的其他資料,如[Cppreference]。例如,當(dāng)我提到一個(gè)標(biāo)準(zhǔn)庫函數(shù)或類時(shí),很容易就能找到它的定義,并且通過查找其文檔,能找到很多相關(guān)的資料。
本書力求把C++作為一個(gè)整體呈現(xiàn)在讀者面前,而非像千層糕一樣逐層地介紹。因此,本書不細(xì)分某個(gè)語言特性是屬于C、C++98的一部分還是新的C++11、C++14或C++17。這種信息可在第16章(歷史和兼容性)中找到。本書聚焦基礎(chǔ)并力求簡潔,但也未能完全抵抗過度闡述新特性的誘惑。這看起來也滿足了很多已經(jīng)了解舊版本C++的讀者的好奇心。
一本程序設(shè)計(jì)語言參考手冊或標(biāo)準(zhǔn)會簡單陳述可以做什么,但程序員通常對學(xué)習(xí)如何用好語言更感興趣。達(dá)到這個(gè)目的一方面要靠主題的選擇,另一方面要靠文字的組織,特別是建議部分。關(guān)于優(yōu)秀的現(xiàn)代C++語言是怎樣構(gòu)成的更多建議可在《C++ Core Guidelines》(C++核心準(zhǔn)則)[Stroustrup, 2015]一書中找到。對于希望繼續(xù)深入探索本書介紹的思想的讀者,這是一本很好的書。你可能注意到了,《C++ Core Guidelines》和本書在建議的呈現(xiàn)上甚至建議的編號方式上都驚人地相似。其中一個(gè)原因是本書第1版是最初的《C++ Core Guidelines》的主要參考資源。
致謝
本書的一些內(nèi)容源自《C++程序設(shè)計(jì)語言(第4版)》(TC++PL4)[Stroustrup, 2013],因此要感謝幫助我完成TC++PL4的所有同仁。
感謝幫助我完成并校對本書第1版的所有同仁。
感謝Morgan Stanley給予我時(shí)間進(jìn)行本書的寫作。感謝哥倫比亞大學(xué)2018年春季課程“使用C++設(shè)計(jì)程序”的所有學(xué)生找出了本書最初草稿中的很多拼寫問題和錯(cuò)誤并給出了很多建設(shè)性的意見。
感謝Paul Anderson、Chuck Allison、Peter Gottschling、William Mons、Charles Wilson和Sergey Zubkov審閱了本書并給出了很多改進(jìn)建議。
本賈尼·斯特勞斯特魯普
曼哈頓,紐約
出版者的話
譯者序
前言
第1章 基礎(chǔ)知識 1
1.1 引言 1
1.2 程序 1
1.3 函數(shù) 3
1.4 類型、變量和算術(shù)運(yùn)算 4
1.4.1 算術(shù)運(yùn)算 5
1.4.2 初始化 6
1.5 作用域和生命周期 7
1.6 常量 8
1.7 指針、數(shù)組和引用 9
1.8 檢驗(yàn) 12
1.9 映射到硬件 14
1.9.1 賦值 14
1.9.2 初始化 15
1.10 建議 16
第2章 用戶自定義類型 18
2.1 引言 18
2.2 結(jié)構(gòu) 18
2.3 類 20
2.4 聯(lián)合 21
2.5 枚舉 22
2.6 建議 23
第3章 模塊化 25
3.1 引言 25
3.2 分別編譯 26
3.3 模塊(C++20) 27
3.4 名字空間 29
3.5 錯(cuò)誤處理 30
3.5.1 異常 30
3.5.2 不變式 32
3.5.3 錯(cuò)誤處理替代 33
3.5.4 合約 35
3.5.5 靜態(tài)斷言 35
3.6 函數(shù)參數(shù)和返回值 36
3.6.1 參數(shù)傳遞 36
3.6.2 返回值 37
3.6.3 結(jié)構(gòu)化綁定 39
3.7 建議 40
第4章 類 41
4.1 引言 41
4.2 具體類型 42
4.2.1 一種算術(shù)類型 42
4.2.2 容器 44
4.2.3 初始化容器 45
4.3 抽象類型 47
4.4 虛函數(shù) 49
4.5 類層次 50
4.5.1 層次結(jié)構(gòu)的益處 52
4.5.2 層次漫游 53
4.5.3 避免資源泄漏 54
4.6 建議 55
第5章 基本操作 57
5.1 引言 57
5.1.1 基本操作 57
5.1.2 類型轉(zhuǎn)換 59
5.1.3 成員初始值 59
5.2 拷貝和移動 60
5.2.1 拷貝容器 60
5.2.2 移動容器 62
5.3 資源管理 63
5.4 常規(guī)操作 65
5.4.1 比較 65
5.4.2 容器操作 65
5.4.3 輸入輸出操作 66
5.4.4 用戶自定義字面值 66
5.4.5 swap() 67
5.4.6 hash<> 67
5.5 建議 67
第6章 模板 69
6.1 引言 69
6.2 參數(shù)化類型 69
6.2.1 約束模板參數(shù)(C++20) 71
6.2.2 值模板參數(shù) 71
6.2.3 模板參數(shù)推斷 72
6.3 參數(shù)化操作 73
6.3.1 函數(shù)模板 73
6.3.2 函數(shù)對象 74
6.3.3 lambda表達(dá)式 75
6.4 模板機(jī)制 77
6.4.1 可變參數(shù)模板 78
6.4.2 別名 78
6.4.3 編譯時(shí)if 79
6.5 建議 80
第7章 概念和泛型編程 81
7.1 引言 81
7.2 概念(C++20) 81
7.2.1 概念的使用 82
7.2.2 基于概念的重載 83
7.2.3 合法代碼 84
7.2.4 概念的定義 84
7.3 泛型編程 86
7.3.1 概念的使用 86
7.3.2 使用模板抽象 86
7.4 可變參數(shù)模板 88
7.4.1 表達(dá)式折疊 89
7.4.2 參數(shù)轉(zhuǎn)發(fā) 90
7.5 模板編譯模型 90
7.6 建議 91
第8章 標(biāo)準(zhǔn)庫概覽 92
8.1 引言 92
8.2 標(biāo)準(zhǔn)庫組件 92
8.3 標(biāo)準(zhǔn)庫頭文件和名字空間 93
8.4 建議 94
第9章 字符串和正則表達(dá)式 95
9.1 引言 95
9.2 字符串 95
9.3 字符串視圖 97
9.4 正則表達(dá)式 99
9.4.1 搜索 99
9.4.2 正則表達(dá)式符號表示 100
9.4.3 迭代器 104
9.5 建議 104
第10章 輸入輸出 106
10.1 引言 106
10.2 輸出 107
10.3 輸入 108
10.4 I/O狀態(tài) 109
10.5 用戶自定義類型的I/O 110
10.6 格式化 111
10.7 文件流 112
10.8 字符串流 112
10.9 C風(fēng)格I/O 113
10.10 文件系統(tǒng) 114
10.11 建議 117
第11章 容器 119
11.1 引言 119
11.2 vector 119
11.2.1 元素 121
11.2.2 范圍檢查 122
11.3 list 123
11.4 map 125
11.5 unordered_map 125
11.6 容器概述 127
11.7 建議 128
第12章 算法 130
12.1 引言 130
12.2 使用迭代器 131
12.3 迭代器類型 133
12.4 流迭代器 134
12.5 謂詞 136
12.6 算法概述 136
12.7 概念(C++20) 137
12.8 容器算法 140
12.9 并行算法 140
12.10 建議 141
第13章 實(shí)用功能 142
13.1 引言 142
13.2 資源管理 142
13.2.1 unique_ptr和shared_ptr 143
13.2.2 move()和forward() 145
13.3 范圍檢查:span 147
13.4 特殊容器 148
13.4.1 array 149
13.4.2 bitset 150
13.4.3 pair和tuple 151
13.5 選擇 152
13.5.1 variant 153
13.5.2 optional 154
13.5.3 any 155
13.6 分配器 155
13.7 時(shí)間 156
13.8 函數(shù)適配器 157
13.8.1 lambda作為適配器 157
13.8.2 mem_fn() 157
13.8.3 function 158
13.9 類型函數(shù) 158
13.9.1 iterator_traits 159
13.9.2 類型謂詞 161
13.9.3 enable_if 161
13.10 建議 162
第14章 數(shù)值 163
14.1 引言 163
14.2 數(shù)學(xué)函數(shù) 163
14.3 數(shù)值算法 164
14.4 復(fù)數(shù) 165
14.5 隨機(jī)數(shù) 166
14.6 向量算術(shù) 167
14.7 數(shù)值限制 168
14.8 建議 168
第15章 并發(fā) 169
15.1 引言 169
15.2 任務(wù)和thread 169
15.3 傳遞參數(shù) 170
15.4 返回結(jié)果 171
15.5 共享數(shù)據(jù) 172
15.6 等待事件 173
15.7 任務(wù)通信 175
15.7.1 future和promise 175
15.7.2 packaged_task 176
15.7.3 async() 177
15.8 建議 178
第16章 歷史和兼容性 180
16.1 歷史 180
16.1.1 大事年表 181
16.1.2 早期的C++ 182
16.1.3 ISO C++標(biāo)準(zhǔn) 184
16.