內容介紹
榮耀與劉未鵬合譯的重量級編程圖書,市面上唯一一本討論C++不足之處,並給出解決方案的圖書。即便是C++陣營里最忠實的信徒,也不得不承認:C++語言並不完美。實際上,世界上也沒有完美的程式語言。
如何克服C++類型系統的不足?在C++中,如何利用約束、契約和斷言來實施軟體設計?如何處理被C++標準所忽略的動態庫、靜態對象以及執行緒等有關的問題?隱式轉換有何替代方案?本書將為你一一解答這些問題。針對C++的每一個不完美之處,本書都具體地分析原因,並探討實用的解決方案。書中也不乏許多作者創新的、你從未聽說過或使用的技術,但這些確實能幫助你成為C++方面的專家。
本書適合有一定經驗的C++程式設計師和項目經理閱讀,也適合對C++編程的一些專門或高級話題感興趣的讀者參考。
作者介紹
Matthew Wilson是一名軟體開發顧問,也是STLSoft庫的創建者。他為雙月刊C/C++ Users Journal撰寫關於將C/C++與其他語言和技術進行整合的專欄文章,同時也是C++ Experts Forum線上專欄作家。Wilson有十餘年C++開發經驗。榮耀,南京師範大學教師。他是一名C++講師和研究者,譯有《C++必知必會》、《C++ Templates全覽》以及《C++ Template Metaprogramming中文版》(中文繁體版)等,並在期刊雜誌上發表過多篇文章。他原任電力自動化研究院工程師與項目經理,是數個企業級信息系統項目負責人,詳見www.royaloo.com。
劉未鵬,南京大學計算機系碩士畢業,現就職於微軟亞洲研究院創新工程中心,部落格地址為http://mindhacks.cn/。
作品目錄
目 錄第一部分基礎知識 1
第1章強制設計:約束、契約和斷言 3
1.1綠蛋和火腿 4
1.2編譯期契約:約束 4
1.2.1must_have_base() 5
1.2.2must_be_subscriptable() 6
1.2.3must_be_subscriptable_
as_decayable_pointer() 6
1.2.4must_be_pod() 7
1.2.5must_be_same_size() 9
1.2.6使用約束 10
1.2.7約束和TMP 11
1.2.8約束:尾聲 11
1.3運行期契約:前置條件、後
置條件和不變式 12
1.3.1前置條件 13
1.3.2後置條件 13
1.3.3類不變式 15
1.3.4檢查?總是進行 16
1.3.5DbC還是不DbC 17
1.3.6運行期契約:尾聲 17
1.4斷言 18
1.4.1獲取訊息 19
1.4.2不恰當的斷言 20
1.4.3語法以及64位指針 21
1.4.4避免使用verify() 21
1.4.5為你的斷言命名 22
1.4.6避免使用#ifdef_DEBUG 23
1.4.7DebugBreak()和int 3 24
1.4.8靜態/編譯期斷言 24
1.4.9斷言:尾聲 26
第2章對象生命期 27
2.1對象生命周期 27
2.2控制你的客戶端 28
2.2.1成員類型 28
2.2.2預設構造函式 28
2.2.3拷貝構造函式 29
2.2.4拷貝賦值 29
2.2.5new和delete 30
2.2.6虛析構 30
2.2.7explicit 31
2.2.8析構函式 31
2.2.9友元 32
2.3MIL及其優點 33
2.3.1取得一塊更大的場地 35
2.3.2成員順序依賴 37
2.3.3offsetof() 38
2.3.4MIL:尾聲 39
第3章資源封裝 40
3.1資源封裝分類 40
3.2POD類型 41
3.2.1直接操縱 41
3.2.2API函式和透明類型 42
3.2.3API函式和不透明類型 42
3.3外覆代理類 43
3.4RRID類型 45
3.4.1預設初始化:緩式初
始化 46
3.4.2未初始化 48
3.5RAII類型 51
3.5.1常性RAII和易變性
RAII 51
3.5.2內部初始化和外部初
始化 53
3.5.3RAII排列 53
3.6RAII:尾聲 54
3.6.1不變式 54
3.6.2錯誤處理 54
第4章數據封裝和值類型 55
4.1數據封裝的分類學 55
4.2值類型和實體類型 56
4.3值類型的分類學 56
4.4開放式類型 58
4.4.1POD開放式類型 58
4.4.2C++數據結構 59
4.5封裝式類型 60
4.6值類型 61
4.7算術值類型 62
4.8值類型:尾聲 63
4.9封裝:尾聲 64
第5章對象訪問模型 68
5.1確定性生命期 68
5.2返回拷貝 70
5.3直接交給調用者 70
5.4共享對象 71
第6章域守衛類 73
6.1值 73
6.2狀態 78
6.3API和服務 83
6.3.1API 83
6.3.2服務 86
6.4語言特性 87
第二部分生存在現實世界 89
第7章ABI 91
7.1共享代碼 91
7.2C ABI需求 93
7.2.1結構布局 93
7.2.2調用約定、符號名以及
目標檔案格式 94
7.2.3靜態連線 94
7.2.4動態連線 95
7.3C++ ABI需求 96
7.3.1對象布局 97
7.3.2虛函式 97
7.3.3調用約定和名字重整 97
7.3.4靜態連線 99
7.3.5動態連線 99
7.4現在知道怎么做了 100
7.4.1extern“C” 100
7.4.2名字空間 103
7.4.3extern“C++” 103
7.4.4獲得C++類的句柄 106
7.4.5 “由實現定義”的隱患 108
第8章跨邊界的對象 110
8.1近乎可移植的虛函式表 110
8.1.1虛函式表布局 111
8.1.2動態操縱虛函式表 113
8.2可移植的虛函式表 114
8.2.1利用宏進行簡化 116
8.2.2兼容的編譯器 116
8.2.3可移植的服務端對象 117
8.2.4簡化可移植接口的
實現 119
8.2.5C客戶代碼 120
8.2.6OAB的約束 120
8.3ABI/OAB尾聲 121
第9章動態庫 123
9.1顯式調用函式 123
9.1.1顯式調用C++函式 124
9.1.2打破C++訪問控制 125
9.2同一性:連線單元和連線
空間 125
9.2.1連線單元 125
9.2.2連線空間 126
9.2.3多重身份 126
9.3生命期 127
9.4版本協調 128
9.4.1丟失的函式 128
9.4.2變化的簽名 128
9.4.3行為的改變 129
9.4.4常量 129
9.5資源所有權 130
9.5.1共享池 130
9.5.2返還給被調用方 130
9.6動態庫:尾聲 131
第10章執行緒 132
10.1對整型值的同步訪問 133
10.1.1作業系統函式 134
10.1.2原子類型 135
10.2對(代碼)塊的同步訪問:
臨界區 136
10.2.1進程間互斥體和進程內互斥體 137
10.2.2自旋互斥體 138
10.3原子整型的性能 139
10.3.1基於互斥體的原子
整型 139
10.3.2運行期按架構派發 141
10.3.3性能比較 142
10.3.4原子整型操作:尾聲 143
10.4多執行緒擴展 144
10.4.1synchronized 144
10.4.2匿名synchronized 147
10.4.3atomic 147
10.5執行緒相關的存儲 148
10.5.1重入 148
10.5.2執行緒相關的數據/線
程局部存儲 148
10.5.3declspec(thread)和
TLS 150
10.5.4Tss庫 150
10.5.5TSS的性能 155
第11章靜態對象 156
11.1非局部靜態對象:全局對象 157
11.1.1編譯單元內的順序性 158
11.1.2編譯單元間的順序性 159
11.1.3利用main()避免全局
變數 161
11.1.4全局對象尾聲:順
序性 162
11.2單件 163
11.2.1Meyers單件 163
11.2.2Alexandrescu單件 164
11.2.3即時Schwarz計數器:
一個極妙的主意 165
11.2.4對API計數 166
11.2.5被計數的API、外覆類、
代理類:最終得到一個
順序化的單件 168
11.3函式範圍內的靜態對象 169
11.3.1犧牲緩式求值能力 171
11.3.2自旋互斥體是救星 171
11.4靜態成員 172
11.4.1解決連線問題 172
11.4.2自適應代碼 174
11.5靜態對象:尾聲 175
第12章最佳化 176
12.1內聯函式 176
12.1.1警惕過早最佳化 176
12.1.2隻含有頭檔案的庫 177
12.2返回值最佳化 177
12.3空基類最佳化 180
12.4空派生類最佳化 183
12.5阻止最佳化 184
第三部分語言相關的議題 188
第13章基本類型 189
13.1可以給我來一個位元組嗎 189
13.1.1標明符號 190
13.1.2一切都在名字之中 190
13.1.3窺探void內部 191
13.1.4額外的安全性 191
13.2固定大小的整型 192
13.2.1平台無關性 193
13.2.2類型相關的行為 195
13.2.3固定大小的整型:
尾聲 197
13.3大整型 198
13.4危險的類型 200
13.4.1引用和臨時對象 200
13.4.2bool 201
第14章數組和指針 204
14.1不要重複你自己 204
14.2數組退化為指針 206
14.2.1下標索引操作符的
交換性 206
14.2.2阻止退化 208
14.3dimensionof() 209
14.4無法將數組傳遞給函式 211
14.5數組總是按地址進行傳遞 214
14.6派生類的數組 215
14.6.1通過指針保存多態
類型 216
14.6.2提供非預設的構造
函式 217
14.6.3隱藏向量式new和
delete 218
14.6.4使用std::vector 218
14.6.5確保類型的大小相同 219
14.7不能擁有多維數組 222
第15章值 226
15.1NULL的是非曲直 226
15.2回到0 232
15.3屈服於事實 235
15.4字面量 236
15.4.1整型 236
15.4.2後綴 238
15.4.3字元串 240
15.5常量 243
15.5.1簡單常量 243
15.5.2類類型常量 244
15.5.3成員常量 245
15.5.4類類型的成員常量 248
第16章關鍵字 251
16.1interface 251
16.2temporary 253
16.3owner 256
16.4explicit(_cast) 261
16.4.1使用顯式訪問函式 263
16.4.2模擬顯式轉換 264
16.4.3使用特性墊片 265
16.5unique 266
16.6final 267
16.7不被支持的關鍵字 267
第17章語法 270
17.1類的代碼布局 270
17.2條件表達式 273
17.2.1“使它布爾” 273
17.2.2一個危險的賦值 275
17.3for 277
17.3.1初始化作用域 277
17.3.2異質初始化類型 278
17.4變數命名 280
17.4.1匈牙利命名法 280
17.4.2成員變數 281
第18章Typedef 284
18.1指針typedef 286
18.2定義裡面有什麼 288
18.2.1概念性的類型定義 288
18.2.2上下文相關的類型
定義 289
18.3別名 292
18.3.1錯誤的概念性類型
互換 293
18.3.2不能對概念性類型進
行重載 294
18.4true_typedef 294
18.5好的、壞的、醜陋的 300
18.5.1好的typedef 300
18.5.2壞的typedef 303
18.5.3可疑的typedef 304
第四部分感知式轉換 308
第19章強制 310
19.1隱式轉換 310
19.2C++中的強制 311
19.3適合使用C強制的場合 312
19.4模仿強制 314
19.5explicit_cast 316
19.6literal_cast 321
19.7union_cast 323
19.8comstl::interface_cast 327
19.8.1interface_cast_addref 328
19.8.2interface_cast_noaddref 329
19.8.3interface_cast_test 329
19.8.4接口強制操作符的
實現 330
19.8.5保護引用計數 333
19.8.6interface_cast_base 334
19.8.7IID_traits 335
19.8.8interface_cast 尾聲 336
19.9boost::polymorphic_cast 337
19.10強制:尾聲 339
第20章墊片 341
20.1擁抱變化 擁抱自由 341
20.2特性墊片 344
20.3邏輯墊片 346
20.4控制墊片 347
20.5轉換墊片 348
20.6複合式墊片概念 350
20.6.1訪問墊片 351
20.6.2返回值生命期 352
20.6.3泛化的類型操縱 354
20.6.4效率方面的考慮 356
20.7名字空間和Koenig查找 357
20.8為何不使用traits 359
20.9結構一致性 360
20.10打破巨石 362
20.11墊片:尾聲 363
第21章飾面 365
21.1輕量級RAII 366
21.2將數據和操作綁定在一起 367
21.2.1pod_veneer 368
21.2.2創建日誌訊息 370
21.2.3減少浪費 371
21.2.4類型安全的訊息類 372
21.3 “擦亮”飾面概念 374
21.4飾面:尾聲 376
第22章螺栓 377
22.1添加功能 377
22.2皮膚選擇 378
22.3非虛重寫 379
22.4巧用作用域 380
22.5擬編譯期多態:逆反式
螺栓 383
22.6參數化多態包裝 384
22.7螺栓:尾聲 386
第23章模板構造函式 387
23.1不易察覺的開銷 389
23.2懸掛引用 389
23.3模板構造函式特化 391
23.4實參代理 392
23.5明確實參的範疇 394
23.6模板構造函式:尾聲 395
第五部分操作符 396
第24章operator bool() 398
24.1operator int() const 398
24.2operator void *() const 399
24.3operator bool() const 400
24.4operator !() const 401
24.5operator boolean const *()
const 401
24.6operator int boolean::*()
const 402
24.7在現實世界中操作 402
24.8operator! 407
第25章快速、非侵入性的字元串
拼接 408
25.1fast_string_concatenator<> 409
25.1.1與用戶自定義的字元
串類協同工作 409
25.1.2將“拼接子”串起來 410
25.1.3fast_string_concatenator
類 411
25.1.4內部實現 413
25.2性能 417
25.3與其他字元串類協作 420
25.3.1整合進標準庫中 420
25.3.2整合進可改動的現存
類中 420
25.3.3與不可更改的類互
操作 420
25.4拼接提示 421
25.5病態括弧 422
25.6標準化 423
第26章你的地址是什麼 424
26.1無法得到真實的地址 424
26.1.1STL式元素存放 424
26.1.2ATL外覆類和CAdapt 425
26.1.3獲取真實的地址 426
26.2在轉換過程中發生了什麼 427
26.3我們返回什麼 429
26.4你的地址是什麼:尾聲 431
第27章下標索引操作符 434
27.1指針轉換與下標索引操作符 434
27.1.1選擇隱式轉換操作符 436
27.1.2選擇下標索引操作符 437
27.2錯誤處理 437
27.3返回值 439
第28章增量操作符 441
28.1缺少後置式操作符 442
28.2效率 443
第29章算術類型 446
29.1類定義 446
29.2預設構造 447
29.3初始化(值構造) 447
29.4拷貝構造函式 450
29.5賦值 450
29.6算術操作符 451
29.7比較操作符 452
29.8訪問值 452
29.9sinteger64 453
29.10截斷、提升以及布爾測試 453
29.10.1截斷 453
29.10.2提升 455
29.10.3布爾測試 455
29.11算術類型:尾聲 456
第30章短路 458
第六部分擴展C++ 460
第31章返回值生命期 461
31.1返回值生命期問題分類 461
31.1.1局部變數 462
31.1.2局部靜態對象 462
31.1.3析構後指針
(Postdestruction Pointers) 462
31.2為何按引用返回 462
31.3解決方案1:
integer_to_string<> 462
31.4解決方案2——TSS 465
31.4.1--declspec(thread) 466
31.4.2Win32 TLS 466
31.4.3平台無關的API 469
31.4.4RVL 470
31.5解決方案3——擴展RVL 470
31.5.1解決執行緒內的RVL-LS問題 471
31.5.2RVL 472
31.6解決方案4——靜態數組大
小決議 472
31.7解決方案5——轉換墊片 474
31.8性能 476
31.9RVL:垃圾收集的大勝利 477
31.10可能的套用 478
31.11返回值生命期:尾聲 478
第32章記憶體 479
32.1記憶體分類 479
32.1.1棧和靜態記憶體 479
32.1.2棧擴張 480
32.1.3堆記憶體 481
32.2兩者之間的折衷 481
32.2.1alloca() 482
32.2.2VLA 483
32.2.3auto_buffer<> 483
32.2.4使用auto_buffer 486
32.2.5EBO,在哪裡 487
32.2.6性能 488
32.2.7堆、棧以及其他 490
32.2.8pod_vector<> 491
32.3配置器 493
32.3.1函式指針 493
32.3.2配置器接口 494
32.3.3每庫初始化(Per-library
Initialization) 495
32.3.4每調用指定(Per-Call
Specification) 496
32.4記憶體:尾聲 496
第33章多維數組 497
33.1激活下標索引操作符 498
33.2運行時確定大小 499
33.2.1可變長數組 499
33.2.2vector< ... vector<T>
... > 500
33.2.3boost::multi_array 501
33.2.4fixed_array_1/2/3/4d 501
33.3編譯期確定大小 505
33.3.1boost::array 506
33.3.2static_array_1/2/3/4d 506
33.4塊訪問 508
33.4.1使用std::fill_n() 509
33.4.2array_size墊片 510
33.5性能 512
33.5.1運行期確定大小 513
33.5.2編譯期確定大小 514
33.6多維數組:尾聲 515
第34章仿函式和區間 516
34.1語法混亂 516
34.2for_all() 517
34.2.1數組 518
34.2.2命名 518
34.3局部仿函式 520
34.3.1手寫循環 520
34.3.2自定義仿函式 521
34.3.3內嵌的仿函式 521
34.3.4溫和一些 523
34.3.5泛化的仿函式:類型隧
道(Type Tunneling) 524
34.3.6再進一步,走得太
遠了 526
34.3.7局部仿函式和回調
API 527
34.4區間 529
34.4.1區間概念 529
34.4.2概念性區間 531
34.4.3可疊代區間 533
34.4.4區間算法和標籤 533
34.4.5過濾器 535
34.4.6虛偽 536
34.5仿函式和區間:尾聲 536
第35章屬性 537
35.1編譯器擴展 539
35.2可供選擇的實現方案 539
35.2.1將屬性的實現分門
別類 540
35.2.2EMO 540
35.3欄位屬性 541
35.3.1field_property_get 541
35.3.2field_property_set 545
35.3.3內置式欄位屬性:
尾聲 546
35.3.4field_property_get_
external 546
35.3.5field_property_set_
external 547
35.3.6Hack掉 547
35.4方法屬性 548
35.4.1method_property_get 548
35.4.2method_property_set 555
35.4.3method_property_getset 555
35.4.4謹防無限循環 557
35.4.5method_property_get
_external 558
35.4.6method_property_set
_external 561
35.4.7method_property_getset
_external 562
35.5靜態屬性 564
35.5.1靜態欄位屬性 564
35.5.2內置式靜態方法屬性 564
35.5.3外置式靜態方法屬性 566
35.6虛屬性 567
35.7屬性的使用 568
35.7.1泛化性 568
35.7.2錯誤診斷中的類型
替換 569
35.8屬性:尾聲 570
附錄A編譯器和庫 572
A.1編譯器 572
A.2庫 573
A.2.1Boost 574
A.2.2STLSoft 574
A.2.3其他庫 574
A.3其他資源 575
A.3.1期刊 575
A.3.2其他語言 575
A.3.3新聞組 576
附錄B“謙虛點,別驕傲” 577
B.1操作符重載 577
B.2後悔DRY 579
B.3偏執式編程 579
B.4精神錯亂 580
附錄CArturius 582
附錄D隨書光碟 583
尾聲 584
參考書目 585