《Imperfect C++中文版》PDF下载

  • 购买积分:17 如何计算积分?
  • 作  者:(美)威尔逊著;荣耀,刘未鹏译
  • 出 版 社:北京:人民邮电出版社
  • 出版年份:2012
  • ISBN:9787115277978
  • 页数:591 页
图书介绍:本书讲解了如何克服c++类型系统的不足;如何利用约束、契约和断言来实施软件设计;如何处理被c++标准所忽略的动态库、静态对象以及线程等有关的问题。针对c++的每一个不完美之处,本书都具体地分析原因,并探讨实用的解决方案。

第一部分 基础知识 1

第1章 强制设计:约束、契约和断言 3

1.1 绿蛋和火腿 4

1.2 编译期契约:约束 4

1.2.1 must_have_base() 5

1.2.2 must_be_subscriptable() 6

1.2.3 must_be_subscriptable_as_decayable_pointer() 6

1.2.4 must_be_pod() 7

1.2.5 must_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.5 DbC还是不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.7 DebugBreak()和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.5 new和delete 30

2.2.6 虚析构 30

2.2.7 explicit 31

2.2.8 析构函数 31

2.2.9 友元 32

2.3 MIL及其优点 33

2.3.1 取得一块更大的场地 35

2.3.2 成员顺序依赖 37

2.3.3 offsetof() 38

2.3.4 MIL:尾声 39

第3章 资源封装 40

3.1 资源封装分类 40

3.2 POD类型 41

3.2.1 直接操纵 41

3.2.2 API函数和透明类型 42

3.2.3 API函数和不透明类型 42

3.3 外覆代理类 43

3.4 RRID类型 45

3.4.1 缺省初始化:缓式初始化 46

3.4.2 未初始化 48

3.5 RAII类型 51

3.5.1 常性RAII和易变性RAII 51

3.5.2 内部初始化和外部初始化 53

3.5.3 RAII排列 53

3.6 RAII:尾声 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.1 POD开放式类型 58

4.4.2 C++数据结构 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.3 API和服务 83

6.3.1 API 83

6.3.2 服务 86

6.4 语言特性 87

第二部分 生存在现实世界 89

第7章 ABI 91

7.1 共享代码 91

7.2 C ABI需求 93

7.2.1 结构布局 93

7.2.2 调用约定、符号名以及目标文件格式 94

7.2.3 静态连接 94

7.2.4 动态连接 95

7.3 C++ 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.1 extern"C" 100

7.4.2 名字空间 103

7.4.3 extern"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.5 C客户代码 120

8.2.6 OAB的约束 120

8.3 ABI/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.1 synchronized 144

10.4.2 匿名synchronized 147

10.4.3 atomic 147

10.5 线程相关的存储 148

10.5.1 重入 148

10.5.2 线程相关的数据/线程局部存储 148

10.5.3 declspec(thread)和TLS 150

10.5.4 Tss库 150

10.5.5 TSS的性能 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.1 Meyers单件 163

11.2.2 Alexandrescu单件 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.2 bool 201

第14章 数组和指针 204

14.1 不要重复你自己 204

14.2 数组退化为指针 206

14.2.1 下标索引操作符的交换性 206

14.2.2 阻止退化 208

14.3 dimensionof() 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.1 NULL的是非曲直 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.1 interface 251

16.2 temporary 253

16.3 owner 256

16.4 explicit(_cast) 261

16.4.1 使用显式访问函数 263

16.4.2 模拟显式转换 264

16.4.3 使用特性垫片 265

16.5 unique 266

16.6 final 267

16.7 不被支持的关键字 267

第17章 语法 270

17.1 类的代码布局 270

17.2 条件表达式 273

17.2.1 “使它布尔” 273

17.2.2 一个危险的赋值 275

17.3 for 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.4 true_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.2 C++中的强制 311

19.3 适合使用C强制的场合 312

19.4 模仿强制 314

19.5 explicit_cast 316

19.6 literal_cast 321

19.7 union_cast 323

19.8 comstl::interface_cast 327

19.8.1 interface_cast_addref 328

19.8.2 interface_cast_noaddref 329

19.8.3 interface_cast_test 329

19.8.4 接口强制操作符的实现 330

19.8.5 保护引用计数 333

19.8.6 interface_cast_base 334

19.8.7 IID_traits 335

19.8.8 interface_cast尾声 336

19.9 boost::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.1 pod_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.1 operator int() const 398

24.2 operator void*() const 399

24.3 operator bool() const 400

24.4 operator!() const 401

24.5 operator boolean const*() const 401

24.6 operator int boolean::*() const 402

24.7 在现实世界中操作 402

24.8 operator! 407

第25章 快速、非侵入性的字符串拼接 408

25.1 fast_string_concatenator<> 409

25.1.1 与用户自定义的字符串类协同工作 409

25.1.2 将“拼接子”串起来 410

25.1.3 fast_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.1 STL式元素存放 424

26.1.2 ATL外覆类和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.9 sinteger64 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.2 Win32 TLS 466

31.4.3 平台无关的API 469

31.4.4 RVL 470

31.5 解决方案3——扩展RVL 470

31.5.1 解决线程内的RVL-LS问题 471

31.5.2 RVL 472

31.6 解决方案4——静态数组大小决议 472

31.7 解决方案5——转换垫片 474

31.8 性能 476

31.9 RVL:垃圾收集的大胜利 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.1 alloca() 482

32.2.2 VLA 483

32.2.3 auto_buffer<> 483

32.2.4 使用auto_buffer 486

32.2.5 EBO,在哪里 487

32.2.6 性能 488

32.2.7 堆、栈以及其他 490

32.2.8 pod_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.2 vector<...vector<T>...> 500

33.2.3 boost::multi_array 501

33.2.4 fixed_array_1/2/3/4d 501

33.3 编译期确定大小 505

33.3.1 boost::array 506

33.3.2 static_array_1/2/3/4d 506

33.4 块访问 508

33.4.1 使用std::fill_n() 509

33.4.2 array_size垫片 510

33.5 性能 512

33.5.1 运行期确定大小 513

33.5.2 编译期确定大小 514

33.6 多维数组:尾声 515

第34章 仿函数和区间 516

34.1 语法混乱 516

34.2 for_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.2 EMO 540

35.3 字段属性 541

35.3.1 field_property_get 541

35.3.2 field_property_set 545

35.3.3 内置式字段属性:尾声 546

35.3.4 field_property_get_external 546

35.3.5 field_property_set_external 547

35.3.6 Hack掉 547

35.4 方法属性 548

35.4.1 method_property_get 548

35.4.2 method_property_set 555

35.4.3 method_property_getset 555

35.4.4 谨防无限循环 557

35.4.5 method_property_get_external 558

35.4.6 method_property_set_external 561

35.4.7 method_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.1 Boost 574

A.2.2 STLSoft 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

附录C Arturius 582

附录D 随书光盘 583

尾声 584

参考书目 585