C++之美:代碼簡(jiǎn)潔、安全又跑得快的30個(gè)要訣
定 價(jià):109 元
- 作者:(英)J. Guy Davidson(J. 蓋伊·戴維森),(加)Kate Gregory(凱特·格雷戈里)
- 出版時(shí)間:2024/7/1
- ISBN:9787121482434
- 出 版 社:電子工業(yè)出版社
- 中圖法分類(lèi):TP312.8
- 頁(yè)碼:320
- 紙張:
- 版次:01
- 開(kāi)本:16開(kāi)
本書(shū)從《C++核心準(zhǔn)則》(C++ Core Guidelines)中精心挑選了 30 條準(zhǔn)則進(jìn)行細(xì)致、深入的講解。內(nèi)容涵蓋C++語(yǔ)言最主要的方面,如類(lèi)型系統(tǒng)、面向?qū)ο、模板和元編程、錯(cuò)誤處理、程序性能、常量性等,其間又恰如其分地穿插了編碼風(fēng)格、設(shè)計(jì)模式等主題。書(shū)中匯集了作者數(shù)十年職業(yè)生涯的經(jīng)驗(yàn)和一些有趣的示例,除了深刻的見(jiàn)解,行文也充滿(mǎn)了趣味性。作者試圖通過(guò)這種突出重點(diǎn)、以點(diǎn)帶面的方式幫助讀者了解并學(xué)習(xí)《C++核心準(zhǔn)則》,進(jìn)而更深入地掌握 C++這門(mén)編程語(yǔ)言,特別是它的"現(xiàn)代”形態(tài)。本書(shū)適合各種經(jīng)驗(yàn)水平的 C++開(kāi)發(fā)者閱讀。
J. Guy Davidson于1980年通過(guò)Acorn Atom首次接觸編程。他青少年時(shí)代的大部分時(shí)間都在各種家用電腦上編寫(xiě)游戲。后來(lái),他從蘇塞克斯大學(xué)獲得了數(shù)學(xué)學(xué)位,開(kāi)始涉足戲劇,還在一個(gè)靈魂樂(lè)隊(duì)中擔(dān)任鍵盤(pán)手。20世紀(jì)90年代初,他決定編寫(xiě)演示程序,并于1997年開(kāi)始在Codemasters的倫敦辦公室工作,從此進(jìn)入游戲行業(yè)。1999年,Davidson加入了Creative Assembly,現(xiàn)在是那里的工程實(shí)踐主管。他主要負(fù)責(zé)《全面戰(zhàn)爭(zhēng)》(Total War)系列游戲的工作,整理早期的游戲目錄,以及提升工程團(tuán)隊(duì)成員的編程水平。他是IGGI咨詢(xún)委員會(huì)、BSI C++小組和ISO C++委員會(huì)的委員,還是ACCU(Association of C/C++ Users,C/C++用戶(hù)協(xié)會(huì))負(fù)責(zé)C++標(biāo)準(zhǔn)相關(guān)事宜的成員,并在ACCU的編程委員會(huì)任職。他是#include Discord服務(wù)器的管理員。他擔(dān)任多個(gè)組織的行為準(zhǔn)則負(fù)責(zé)人,在C++會(huì)議和各種聚會(huì)上發(fā)言,特別是關(guān)于在標(biāo)準(zhǔn)庫(kù)中增加線性代數(shù)的議題。Kate Gregory接觸編程、與幾位最親密的朋友結(jié)識(shí),以及丈夫的相識(shí),都發(fā)生在1977年的滑鐵盧大學(xué),所有這些她從未后悔過(guò)。她的學(xué)位是化學(xué)工程,這正說(shuō)明你很難從一個(gè)人的學(xué)位中看出什么。她在加拿大安大略省鄉(xiāng)下的地下室有一個(gè)小房間,里面放著一些古老的計(jì)算機(jī):PET、C64、手工焊接的6502系統(tǒng)等,她把這些作為那個(gè)單純年代的紀(jì)念品。自1986年起,她與丈夫一起經(jīng)營(yíng)Gregory咨詢(xún)公司,幫助世界各地的客戶(hù)更好地開(kāi)展業(yè)務(wù)。Kate曾在五個(gè)大洲做過(guò)主題演講,愛(ài)發(fā)掘一些改變認(rèn)知的真相,然后與人分享,她還投入大量的時(shí)間在各種C++活動(dòng)中做志愿者。其中“#include ”是她的最?lèi)?ài),該社區(qū)正在改變這個(gè)行業(yè),使其更受歡迎也更具包容性。他們的Discord服務(wù)器是一處溫馨的場(chǎng)所,初學(xué)者在那里可以學(xué)習(xí)C++,也可以為WG21合寫(xiě)文章以改變我們所使用的編程語(yǔ)言,或者做任何介于兩者之間的事情。
王江平,Autodesk軟件開(kāi)發(fā)工程師,畢業(yè)于同濟(jì)大學(xué)/上海交通大學(xué),愛(ài)編程,愛(ài)讀書(shū),愛(ài)翻譯,愛(ài)C++。譯有《C#3.0設(shè)計(jì)模式》、《敏捷開(kāi)發(fā)的藝術(shù)》、《軟件開(kāi)發(fā)者路線圖》、《Java語(yǔ)言精粹》、《Python計(jì)算與編程實(shí)踐》、《Cucumber:行為驅(qū)動(dòng)開(kāi)發(fā)指南》等書(shū)籍。(微博@steedhorse,歡迎交流。)
第1章 避重就輕不可取 1
1.1 P.2:使用ISO標(biāo)準(zhǔn)C++編寫(xiě)代碼 2
什么是ISO標(biāo)準(zhǔn)C++ 2
封裝差異 4
了解以前的用法 8
緊跟標(biāo)準(zhǔn)的發(fā)展 9
1.2 F.51:在有選擇的情況下,優(yōu)先使用默認(rèn)參數(shù)而非重載 12
引言 12
改進(jìn)抽象概念:是增加參數(shù)還是重載 13
微妙的重載解決 14
回到示例代碼 16
默認(rèn)參數(shù)天然的明確性 18
函數(shù)重載的替代方案 19
有時(shí)必須重載 19
小結(jié) 20
1.3 C.45:不要定義僅初始化數(shù)據(jù)成員的默認(rèn)構(gòu)造函數(shù),而應(yīng)使用類(lèi)內(nèi)成員
?初始化 21
為什么要有默認(rèn)構(gòu)造函數(shù) 21
你是怎樣初始化數(shù)據(jù)成員的 22
兩個(gè)人維護(hù)一個(gè)類(lèi)時(shí)會(huì)怎樣 25
小結(jié) 27
1.4 C.131:避免平凡的get和set函數(shù) 28
一種古老的慣用法 28
抽象 29
單純的封裝 31
類(lèi)不變式 34
名詞和動(dòng)詞 36
小結(jié) 37
1.5 ES.10:每條語(yǔ)句只聲明一個(gè)名字 38
我來(lái)引入你 38
向后兼容 40
寫(xiě)出更加清晰的聲明 42
結(jié)構(gòu)式綁定 43
小結(jié) 44
1.6 NR.2:不強(qiáng)求函數(shù)只用一條return語(yǔ)句 45
規(guī)則會(huì)演化 45
確保資源得到清理 47
使用RAII 50
編寫(xiě)好的函數(shù) 52
小結(jié) 54
第2章 不要傷害自己 55
2.1 P.11:將凌亂的構(gòu)造封裝起來(lái),而不是使其散布于代碼中 56
“一口吞”式做法 56
封裝一種凌亂的構(gòu)造意味著什么 58
語(yǔ)言的目的和抽象的本質(zhì) 60
抽象的層次 63
通過(guò)重構(gòu)和分割實(shí)現(xiàn)抽象 64
小結(jié) 65
2.2 I.23:盡量減少函數(shù)參數(shù) 66
他們應(yīng)該掙多少 66
通過(guò)抽象簡(jiǎn)化問(wèn)題 68
盡可能少,但不要更少 70
現(xiàn)實(shí)例子 72
小結(jié) 73
2.3 I.26:使用C風(fēng)格子集獲取跨編譯器的ABI 74
創(chuàng)建程序庫(kù) 74
什么是ABI 75
最小的C風(fēng)格子集 77
異常的傳播 79
小結(jié) 80
2.4 C.47:按聲明的順序定義并初始化成員變量 82
小結(jié) 90
2.5 CP.3:盡量減少可寫(xiě)數(shù)據(jù)的顯式共享 91
傳統(tǒng)執(zhí)行模型 91
等等,不止這些 93
避免死鎖和數(shù)據(jù)競(jìng)爭(zhēng) 95
拋開(kāi)鎖和互斥體 97
小結(jié) 100
2.6 T.120:只在真正需要時(shí)使用模板元編程 101
std::enable_if => requires 108
小結(jié) 112
第3章 別再使用 113
3.1 I.11:切勿通過(guò)原生指針(T*)或引用(T&)轉(zhuǎn)移所有權(quán) 114
使用自由存儲(chǔ)區(qū) 114
智能指針的性能成本 117
使用未修飾的引用語(yǔ)義 118
gsl::owner 119
小結(jié) 121
3.2 I.3:避免使用單例 122
全局對(duì)象是不好的 122
單例設(shè)計(jì)模式 123
靜態(tài)初始化順序的尷尬 123
如何隱藏一個(gè)單例 125
但它就該只有一份 127
等一下…… 128
小結(jié) 130
3.3 C.90:使用構(gòu)造函數(shù)和賦值運(yùn)算符,而不是memset和memcpy 131
追求最優(yōu)性能 131
構(gòu)造函數(shù)的巨大開(kāi)銷(xiāo) 132
最簡(jiǎn)單的類(lèi) 133
C++標(biāo)準(zhǔn)到底在說(shuō)什么 135
那么,memcpy呢 137
永遠(yuǎn)不要低估編譯器 139
小結(jié) 140
3.4 ES.50:不要用強(qiáng)制轉(zhuǎn)換去除const限定符 141
故事時(shí)間 141
處理更大的數(shù)據(jù)量 142
const防火墻 143
實(shí)現(xiàn)雙接口 144
緩存和懶惰求值 146
兩種類(lèi)型的const 147
const驚奇篇 149
小結(jié) 150
3.5 E.28:避免基于全局狀態(tài)(如errno)的錯(cuò)誤處理 151
錯(cuò)誤處理很難 151
C和errno 151
返回錯(cuò)誤代碼 153
異常 154
<system_error> 154
Boost.Outcome 155
錯(cuò)誤處理為何這樣難 156
隧道盡頭的光 158
小結(jié) 159
3.6 SF.7:不要在頭文件的全局作用域?qū)憉sing namespace 160
不要這樣做 160
消除歧義 161
使用using 162
符號(hào)去了哪里 163
一個(gè)更加隱蔽的問(wèn)題 166
解決作用域解析運(yùn)算符的雜亂問(wèn)題 168
誘惑與墮落 169
小結(jié) 169
第4章 正確使用新特性 171
4.1 F.21:優(yōu)先選擇結(jié)構(gòu)體或元組返回多個(gè)“輸出”值 172
函數(shù)簽名的形式 172
文檔和注解 173
現(xiàn)在可以返回對(duì)象了 174
也可以返回元組 177
使用非const引用傳遞和返回 179
小結(jié) 182
4.2 Enum.3:優(yōu)先選擇class枚舉而不是“普通”枚舉 183
常量 183
作用域枚舉 185
基礎(chǔ)類(lèi)型 187
隱式轉(zhuǎn)換 188
小結(jié) 190
后記 190
4.3 ES.5:保持作用域短小 191
作用域的性質(zhì) 191
塊作用域 192
名字空間作用域 193
類(lèi)作用域 196
函數(shù)參數(shù)作用域 198
枚舉作用域 199
模板參數(shù)作用域 200
作用域作為上下文 201
小結(jié) 202
4.4 Con.5:使用constexpr表示編譯時(shí)可以計(jì)算的值 203
從const到constexpr 203
默認(rèn)的C++ 205
使用constexpr 206
inline 210
constevel 211
constinit 212
小結(jié) 213
4.5 T.1:使用模板提高代碼的抽象層次 214
故事時(shí)間 214
提高抽象的層次 216
函數(shù)模板和抽象 218
類(lèi)模板和抽象 220
命名很難 222
小結(jié) 223
4.6 T.10:為所有模板參數(shù)指定概念 224
來(lái)龍去脈 224
約束你的參數(shù) 226
如何抽象你的概念 229
通過(guò)概念分解 232
小結(jié) 233
第5章 默認(rèn)寫(xiě)出好代碼 234
5.1 P.4:在理想情況下,程序應(yīng)具有靜態(tài)類(lèi)型安全性 235
類(lèi)型安全是C++的一項(xiàng)安全特性 235
聯(lián)合體 237
類(lèi)型轉(zhuǎn)換 238
無(wú)符號(hào)數(shù) 241
緩沖區(qū)和大小 244
小結(jié) 245
5.2 P.10:優(yōu)先選擇不可變數(shù)據(jù)而不是可變數(shù)據(jù) 246
錯(cuò)誤的默認(rèn)設(shè)置 246
函數(shù)聲明中的常量性 248
小結(jié) 252
5.3 I.30:封裝違反規(guī)則的部分 253
隱藏生活中不悅目的東西 253
保全體面 255
小結(jié) 260
5.4 ES.22:初始值確定后再聲明變量 261
表達(dá)式和語(yǔ)句的重要性 261
C風(fēng)格的聲明 262
先聲明后初始化 263
盡可能推遲的聲明 264
上下文特定功能的局部化 266
消除狀態(tài) 268
小結(jié) 270
5.5 Per.7:為促成優(yōu)化而設(shè)計(jì) 271
幀率最大化 271
離硬件更遠(yuǎn)之后 273
通過(guò)抽象進(jìn)行優(yōu)化 276
小結(jié) 278
5.6 E.6:使用RAII防止泄漏 279
確定性析構(gòu) 279
文件泄漏 281
為什么要做這些 284
似乎還是有點(diǎn)兒多:未來(lái)的可能性 286
從哪里獲得這些工具 289
后記 291
跋 293
【C++核心準(zhǔn)則精選】
P.2:使用ISO標(biāo)準(zhǔn)C++編寫(xiě)代碼(1.1節(jié))[ 可以在GitHub或者GitHub Pages上找到C++ Core Guidelines,查看詳細(xì)內(nèi)容。]
P.4:在理想情況下,程序應(yīng)具有靜態(tài)類(lèi)型安全性(5.1節(jié))
P.10:優(yōu)先選擇不可變數(shù)據(jù)而不是可變數(shù)據(jù)(5.2節(jié))
P.11:將凌亂的構(gòu)造封裝起來(lái),而不是使其散布于代碼中(2.1節(jié))
I.3:避免使用單例(3.2節(jié))
I.11:切勿通過(guò)原生指針(T*)或引用(T&)轉(zhuǎn)移所有權(quán)(3.1節(jié))
I.23:盡量減少函數(shù)參數(shù)(2.2節(jié))
I.26:使用C風(fēng)格子集獲取跨編譯器的ABI(2.3節(jié))
I.30:封裝違反規(guī)則的部分(5.3節(jié))
F.21:優(yōu)先選擇結(jié)構(gòu)體或元組返回多個(gè)“輸出”值(4.1節(jié))
F.51:在有選擇的情況下,優(yōu)先使用默認(rèn)參數(shù)而非重載(1.2節(jié))
C.45:不要定義僅初始化數(shù)據(jù)成員的默認(rèn)構(gòu)造函數(shù),而應(yīng)該使用類(lèi)內(nèi)成員初始化(1.3節(jié))
C.47:按聲明的順序定義并初始化成員變量(2.4節(jié))
C.90:使用構(gòu)造函數(shù)和賦值運(yùn)算符,而不是memset和memcpy(3.3節(jié))
C.131:避免平凡的get和set函數(shù)(1.4節(jié))
Enum.3:優(yōu)先選擇class枚舉而不是“普通”枚舉(4.2節(jié))
ES.5:保持作用域短。4.3節(jié))
ES.10:每條語(yǔ)句只聲明一個(gè)名字(1.5節(jié))
ES.22:初始值確定后再聲明變量(5.4節(jié))
ES.50:不要用強(qiáng)制轉(zhuǎn)換去除const限定符(3.4節(jié))
Per.7:為促成優(yōu)化而設(shè)計(jì)(5.5節(jié))
CP.3:盡量減少可寫(xiě)數(shù)據(jù)的顯式共享(2.5節(jié))
E.6:使用RAII防止泄漏(5.6節(jié))
E.28:避免基于全局狀態(tài)(如errno)的錯(cuò)誤處理(3.5節(jié))
Con.5:使用constexpr表示編譯時(shí)可以計(jì)算的值(4.4節(jié))
T.1:使用模板提高代碼的抽象層次(4.5節(jié))
T.10:為所有模板參數(shù)指定概念(4.6節(jié))
T120:只在真正需要時(shí)使用模板元編程(2.6節(jié))
SF.7:不要在頭文件的全局作用域?qū)憉sing namespace(3.6節(jié))
NR.2:不強(qiáng)求函數(shù)只用一條return語(yǔ)句(1.6節(jié))