目 录
第 1章 绪论 1
1.1 C++简史 1
1.1.1 与C语言的关系 1
1.1.2 C++的优点 1
1.1.3 C++标准的发展历程 1
1.1.4 哪些人使用C++程序 2
1.2 编写C++应用程序 2
1.2.1 生成可执行文件的步骤 2
1.2.2 分析并修复错误 2
1.2.3 集成开发环境 2
1.2.4 编写第 一个C++应用程序 3
1.2.5 生成并执行第 一个C++应用程序 4
1.2.6 理解编译错误 4
1.3 C++11新增的功能 5
1.4 总结 5
1.5 问与答 5
1.6 作业 6
1.6.1 测验 6
1.6.2 练习 6
第 2章 C++程序的组成部分 7
2.1 Hello World程序的组成部分 7
2.1.1 预处理器编译指令#include 7
2.1.2 程序的主体-main() 8
2.1.3 返回值 8
2.2 名称空间的概念 9
2.3 C++代码中的注释 10
2.4 C++函数 10
2.5 使用std::cin和std::cout执行基本输入输出操作 12
2.6 总结 13
2.7 问与答 13
2.8 作业 13
2.8.1 测验 14
2.8.2 练习 14
第3章 使用变量和常量 15
3.1 什么是变量 15
3.1.1 内存和寻址概述 15
3.1.2 声明变量以访问和使用内存 15
3.1.3 声明并初始化多个类型相同的变量 17
3.1.4 理解变量的作用域 17
3.1.5 全局变量 18
3.2 编译器支持的常见C++变量类型 19
3.2.1 使用bool变量存储布尔值 20
3.2.2 使用char变量存储字符 20
3.2.3 有符号整数和无符号整数的概念 20
3.2.4 有符号整型short、int、long和long long 21
3.2.5 无符号整型unsigned short、unsigned int、unsigned long和unsigned long long 21
3.2.6 浮点类型float和double 21
3.3 使用sizeof确定变量的长度 22
3.4 使用typedef替换变量类型 24
3.5 什么是常量 24
3.5.1 字面常量 25
3.5.2 使用const将变量声明为常量 25
3.5.3 使用constexpr声明常量 26
3.5.4 枚举常量 26
3.5.5 使用#define定义常量 27
3.6 给变量和常量命名 28
3.7 不能用作常量或变量名的关键字 28
3.8 总结 29
3.9 问与答 29
3.10 作业 30
3.10.1 测验 30
3.10.2 练习 30
第4章 管理数组和字符串 31
4.1 什么是数组 31
4.1.1 为何需要数组 31
4.1.2 声明和初始化静态数组 32
4.1.3 数组中的数据是如何存储的 32
4.1.4 访问存储在数组中的数据 33
4.1.5 修改存储在数组中的数据 34
4.2 多维数组 35
4.2.1 声明和初始化多维数组 36
4.2.2 访问多维数组中的元素 36
4.3 动态数组 37
4.4 C风格字符串 38
4.5 C++字符串:使用std::string 40
4.6 总结 41
4.7 问与答 41
4.8 作业 42
4.8.1 测验 42
4.8.2 练习 42
第5章 使用表达式、语句和运算符 43
5.1 语句 43
5.2 复合语句(语句块) 44
5.3 使用运算符 44
5.3.1 赋值运算符(=) 44
5.3.2 理解左值和右值 44
5.3.3 加法运算符(+)、减法运算符(?)、乘法运算符(*)、除法运算符(/)和求模运算符(%) 44
5.3.4 递增运算符(++)和递减运算符(--) 45
5.3.5 前缀还是后缀 45
5.3.6 相等运算符(==)和不等运算符(!=) 47
5.3.7 关系运算符 48
5.3.8 逻辑运算NOT、AND、OR和XOR 49
5.3.9 使用C++逻辑运算NOT(!)、AND(&&)和OR(||) 50
5.3.10 按位运算符NOT(~)、AND(&)、OR(|)和XOR(^) 53
5.3.11 按位右移运算符(>>)和左移运算符(<<) 54
5.3.12 复合赋值运算符 55
5.3.13 使用运算符sizeof确定变量占用的内存量 56
5.3.14 运算符优先级 57
5.4 总结 58
5.5 问与答 59
5.6 作业 59
5.6.1 测验 59
5.6.2 练习 59
第6章 控制程序流程 60
6.1 使用if...else有条件地执行 60
6.1.1 使用if...else进行条件编程 61
6.1.2 有条件地执行多条语句 62
6.1.3 嵌套if语句 63
6.1.4 使用switch-case进行条件处理 66
6.1.5 使用运算符?:进行条件处理 68
6.2 在循环中执行代码 69
6.2.1 不成熟的goto循环 69
6.2.2 while循环 70
6.2.3 do...while循环 72
6.2.4 for循环 73
6.3 使用continue和break修改循环的行为 75
6.3.1 不结束的循环-无限循环 75
6.3.2 控制无限循环 76
6.4 编写嵌套循环 78
6.4.1 使用嵌套循环遍历多维数组 79
6.4.2 使用嵌套循环计算斐波纳契数列 80
6.5 总结 81
6.6 问与答 81
6.7 作业 82
6.7.1 测验 82
6.7.2 练习 82
第7章 使用函数组织代码 83
7.1 为何需要函数 83
7.1.1 函数原型是什么 84
7.1.2 函数定义是什么 85
7.1.3 函数调用和实参是什么 85
7.1.4 编写接受多个参数的函数 85
7.1.5 编写没有参数和返回值的函数 86
7.1.6 带默认值的函数参数 87
7.1.7 递归函数-调用自己的函数 88
7.1.8 包含多条return语句的函数 89
7.2 使用函数处理不同类型的数据 90
7.2.1 函数重载 90
7.2.2 将数组传递给函数 92
7.2.3 按引用传递参数 93
7.3 微处理器如何处理函数调用 94
7.3.1 内联函数 94
7.3.2 lambda函数 96
7.4 总结 97
7.5 问与答 97
7.6 作业 97
7.6.1 测验 97
7.6.2 练习 98
第8章 阐述指针和引用 99
8.1 什么是指针 99
8.1.1 声明指针 99
8.1.2 使用引用运算符(&)获取变量的地址 100
8.1.3 使用指针存储地址 101
8.1.4 使用解除引用运算符(*)访问指向的数据 102
8.1.5 将sizeof()用于指针的结果 104
8.2 动态内存分配 105
8.2.1 使用new和delete动态地分配和释放内存 105
8.2.2 将递增和递减运算符(++和--)用于指针的结果 107
8.2.3 将关键字const用于指针 109
8.2.4 将指针传递给函数 109
8.2.5 数组和指针的类似之处 110
8.3 使用指针时常犯的编程错误 112
8.3.1 内存泄露 112
8.3.2 指针指向无效的内存单元 112
8.3.3 悬浮指针(也叫迷途或失控指针) 113
8.4 指针编程**佳实践 114
8.4.1 检查使用new发出的分配请求是否得到满足 115
8.5 引用是什么 117
8.5.1 是什么让引用很有用 117
8.5.2 将关键字const用于引用 118
8.5.3 按引用向函数传递参数 119
8.6 总结 119
8.7 问与答 120
8.8 作业 121
8.8.1 测验 121
8.8.2 练习 121
第9章 类和对象 122
9.1 类和对象 122
9.1.1 声明类 123
9.1.2 实例化对象 123
9.1.3 使用句点运算符访问成员 123
9.1.4 使用指针运算符(->)访问成员 124
9.2 关键字public和private 125
9.2.1 使用关键字private实现数据抽象 126
9.3 构造函数 127
9.3.1 声明和实现构造函数 128
9.3.2 何时及如何使用构造函数 128
9.3.3 重载构造函数 130
9.3.4 没有默认构造函数的类 131
9.3.5 带默认值的构造函数参数 133
9.3.6 包含初始化列表的构造函数 133
9.4 析构函数 135
9.4.1 声明和实现析构函数 135
9.4.2 何时及如何使用析构函数 135
9.5 复制构造函数 137
9.5.1 浅复制及其存在的问题 137
9.5.2 使用复制构造函数确保深复制 139
9.5.3 有助于改善性能的移动构造函数 142
9.6 构造函数和析构函数的其他用途 143
9.6.1 不允许复制的类 143
9.6.2 只能有一个实例的单例类 144
9.6.3 禁止在栈中实例化的类 146
9.7 this指针 147
9.8 将sizeof()用于类 148
9.9 结构不同于类的地方 150
9.10 声明友元 150
9.11 总结 152
9.12 问与答 152
9.13 作业 153
9.13.1 测验 153
9.13.2 练习 153
第 10章 实现继承 154
10.1 继承基础 154
10.1.1 继承和派生 154
10.1.2 C++派生语法 155
10.1.3 访问限定符protected 157
10.1.4 基类初始化-向基类传递参数 159
10.1.5 在派生类中覆盖基类的方法 160
10.1.6 调用基类中被覆盖的方法 162
10.1.7 在派生类中调用基类的方法 162
10.1.8 在派生类中隐藏基类的方法 164
10.1.9 构造顺序 165
10.1.10 析构顺序 166
10.2 私有继承 167
10.3 保护继承 169
10.4 切除问题 171
10.5 多继承 171
10.6 总结 174
10.7 问与答 174
10.8 作业 174
10.8.1 测验 174
10.8.2 练习 174
第 11章 多态 176
11.1 多态基础 176
11.1.1 为何需要多态行为 176
11.1.2 使用虚函数实现多态行为 177
11.1.3 为何需要虚构造函数 179
11.1.4 虚函数的工作原理——理解虚函数表 182
11.1.5 抽象基类和纯虚函数 184
11.2 使用虚继承解决菱形问题 186
11.3 可将复制构造函数声明为虚函数吗 189
11.4 总结 191
11.5 问与答 192
11.6 作业 192
11.6.1 测验 192
11.6.2 练习 193
第 12章 运算符类型与运算符重载 194
12.1 C++运算符 194
12.2 单目运算符 195
12.2.1 单目运算符的类型 195
12.2.2 单目递增与单目递减运算符 195
12.2.3 转换运算符 198
12.2.4 解除引用运算符(*)和成员选择运算符(->) 199
12.3 双目运算符 202
12.3.1 双目运算符的类型 202
12.3.2 双目加法与双目减法运算符 202
12.3.3 实现运算符+=与(= 204
12.3.4 重载等于运算符(==)和不等运算符(!=) 206
12.3.5 重载运算符<、>、<=和>= 207
12.3.6 重载复制赋值运算符(=) 209
12.3.7 下标运算符 211
12.4 函数运算符operator() 214
12.5 不能重载的运算符 219
12.6 总结 219
12.7 问与答 220
12.8 作业 220
12.8.1 测验 220
12.8.2 练习 220
第 13章 类型转换运算符 221
13.1 为何需要类型转换 221
13.2 为何有些C++程序员不喜欢C风格类型转换 222
13.3 C++类型转换运算符 222
13.3.1 使用static_cast 222
13.3.2 使用dynamic_cast和运行阶段类型识别 223
13.3.3 使用reinterpret_cast 225
13.3.4 使用const_cast 226
13.4 C++类型转换运算符存在的问题 226
13.5 总结 227
13.6 问与答 227
13.7 作业 228
13.7.1 测验 228
13.7.2 练习 228
第 14章 宏和模板简介 229
14.1 预处理器与编译器 229
14.2 使用#define定义常量 229
14.3 使用#define编写宏函数 232
14.3.1 为什么要使用括号 233
14.3.2 使用assert宏验证表达式 234
14.3.3 使用宏函数的优点和缺点 235
14.4 模板简介 235
14.4.1 模板声明语法 235
14.4.2 各种类型的模板声明 236
14.4.3 模板函数 236
14.4.4 模板与类型安全 238
14.4.5 模板类 238
14.4.6 模板的实例化和具体化 239
14.4.7 声明包含多个参数的模板 239
14.4.8 声明包含默认参数的模板 240
14.4.9 一个模板示例 240
14.4.10 模板类和静态成员 241
14.4.11 在实际C++编程中使用模板 243
14.5 总结 243
14.6 问与答 244
14.7 作业 244
14.7.1 测验 244
14.7.2 练习 244
第 15章 标准模板库简介 245
15.1 STL容器 245
15.1.1 顺序容器 245
15.1.2 关联容器 246
15.1.3 选择正确的容器 246
15.1.4 容器适配器 247
15.2 STL迭代器 247
15.3 STL算法 248
15.4 使用迭代器在容器和算法之间交互 248
15.5 STL字符串类 250
15.6 总结 250
15.7 问与答 250
15.8 作业 251
第 16章 STL string类 252
16.1 为何需要字符串操作类 252
16.2 使用STL string类 253
16.2.1 实例化和复制STL string 253
16.2.2 访问std::string的字符内容 254
16.2.3 拼接字符串 256
16.2.4 在string中查找字符或子字符串 257
16.2.5 截短STL string 259
16.2.6 字符串反转 260
16.2.7 字符串的大小写转换 261
16.3 基于模板的STL string实现 262
16.4 总结 262
16.5 问与答 262
16.6 作业 263
16.6.1 测验 263
16.6.2 练习 263
第 17章 STL动态数组类 264
17.1 std::vector的特点 264
17.2 典型的vector操作 264
17.2.1 实例化vector 264
17.2.2 使用push_back()在末尾插入元素 266
17.2.3 使用insert()在指定位置插入元素 267
17.2.4 使用数组语法访问vector中的元素 269
17.2.5 使用指针语法访问vector中的元素 270
17.2.6 删除vector中的元素 271
17.3 理解大小和容量 272
17.4 STL deque 类 273
17.5 总结 275
17.6 问与答 275
17.7 作业 276
17.7.1 测验 276
17.7.2 练习 276
第 18章 STL list和forward_list 277
18.1 std::list的特点 277
18.2 基本的list操作 277
18.2.1 实例化std::list对象 277
18.2.2 在list开头或末尾插入元素 279
18.2.3 在list中间插入元素 280
18.2.4 删除list中的元素 282
18.3 对list中的元素进行反转和排序 283
18.3.1 使用list::reverse()反转元素的排列顺序 283
18.3.2 对元素进行排序 284
18.3.3 对包含对象的list进行排序以及删除其中的元素 286
18.4 总结 290
18.5 问与答 290
18.6 作业 291
18.6.1 测验 291
18.6.2 练习 291
第 19章 STL集合类 292
19.1 简介 292
19.2 STL set和multiset的基本操作 293
19.2.1 实例化std::set对象 293
19.2.2 在set或multiset中插入元素 294
19.2.3 在STL set或multiset中查找元素 296
19.2.4 删除STL set或multiset中的元素 297
19.3 使用STL set和multiset的优缺点 300
19.4 总结 303
19.5 问与答 303
19.6 作业 304
19.6.1 测验 304
19.6.2 练习 304
第 20章 STL映射类 305
20.1 STL映射类简介 305
20.2 std::map和std::multimap的基本操作 306
20.2.1 实例化std::map和std::multimap 306
20.2.2 在STL map或multimap中插入元素 307
20.2.3 在STL map或multimap中查找元素 309
20.2.4 在STL multimap中查找元素 311
20.2.5 删除STL map或multimap中的元素 312
20.3 提供自定义的排序谓词 313
20.3.1 散列表的工作原理 316
20.3.2 使用C++11散列表unordered_map和unordered_multimap 316
20.4 总结 319
20.5 问与答 319
20.6 作业 320
20.6.1 测验 320
20.6.2 练习 320
第 21章 理解函数对象 321
21.1 函数对象与谓词的概念 321
21.2 函数对象的典型用途 321
21.2.1 一元函数 321
21.2.2 一元谓词 325
21.2.3 二元函数 326
21.2.4 二元谓词 328
21.3 总结 330
21.4 问与答 330
21.5 作业 330
21.5.1 测验 330
21.5.2 练习 330
第 22章 C++ lambda表达式 331
22.1 lambda表达式是什么 331
22.2 如何定义lambda表达式 332
22.3 一元函数对应的lambda表达式 332
22.4 一元谓词对应的lambda表达式 333
22.5 通过捕获列表接受状态变量的lambda表达式 334
22.6 lambda表达式的通用语法 335
22.7 二元函数对应的lambda表达式 336
22.8 二元谓词对应的lambda表达式 337
22.9 总结 339
22.10 问与答 340
22.11 作业 340
22.11.1 测验 340
22.11.2 练习 340
第 23章 STL算法 341
23.1 什么是STL算法 341
23.2 STL算法的分类 341
23.2.1 非变序算法 341
23.2.2 变序算法 342
23.3 使用STL算法 343
23.3.1 根据值或条件查找元素 343
23.3.2 计算包含给定值或满足给定条件的元素数 345
23.3.3 在集合中搜索元素或序列 346
23.3.4 将容器中的元素初始化为指定值 348
23.3.5 使用std::generate()将元素设置为运行阶段生成的值 349
23.3.6 使用for_each()处理指定范围内的元素 350
23.3.7 使用std::transform()对范围进行变换 352
23.3.8 复制和删除操作 354
23.3.9 替换值以及替换满足给定条件的元素 356
23.3.10 排序、在有序集合中搜索以及删除重复元素 357
23.3.11 将范围分区 359
23.3.12 在有序集合中插入元素 360
23.4 总结 362
23.5 问与答 362
23.6 作业 363
23.6.1 测验 363
23.6.2 练习 363
第 24章 自适应容器:栈和队列 364
24.1 栈和队列的行为特征 364
24.1.1 栈 364
24.1.2 队列 365
24.2 使用STL stack类 365
24.2.1 实例化stack 365
24.2.2 stack的成员函数 366
24.2.3 使用push()和pop()在栈顶插入和删除元素 366
24.3 使用STL queue类 367
24.3.1 实例化queue 368
24.3.2 queue的成员函数 368
24.3.3 使用push()在队尾插入以及使用pop()从队首删除 369
24.4 使用STL优先级队列 370
24.4.1 实例化priority_queue类 370
24.4.2 priority_queue的成员函数 371
24.4.3 使用push()在priority_queue末尾插入以及使用pop()在priority_queue开头删除 372
24.5 总结 373
24.6 问与答 373
24.7 作业 374
24.7.1 测验 374
24.7.2 练习 374
第 25章 使用STL位标志 375
25.1 bitset类 375
25.2 使用std::bitset及其成员 376
25.2.1 std:bitset的运算符 376
25.2.2 std::bitset的成员方法 377
25.3 vector
25.3.1 实例化vector
25.3.2 vector
25.4 总结 380
25.5 问与答 380
25.6 作业 381
25.6.1 测验 381
25.6.2 练习 381
第 26章 理解智能指针 382
26.1 什么是智能指针 382
26.1.1 常规(原始)指针存在的问题 382
26.1.2 智能指针有何帮助 383
26.2 智能指针是如何实现的 383
26.3 智能指针类型 384
26.3.1 深复制 384
26.3.2 写时复制机制 385
26.3.3 引用计数智能指针 386
26.3.4 引用链接智能指针 386
26.3.5 破坏性复制 386
26.4 深受欢迎的智能指针库 389
26.5 总结 389
26.6 问与答 389
26.7 作业 390
26.7.1 测试 390
26.7.2 练习 390
第 27章 使用流进行输入和输出 391
27.1 流的概述 391
27.2 重要的C++流类和流对象 391
27.3 使用std::cout将指定格式的数据写入控制台 392
27.3.1 使用std::cout修改数字的显示格式 393
27.3.2 使用std::cout对齐文本和设置字段宽度 394
27.4 使用std::cin进行输入 395
27.4.1 使用std::cin将输入读取到基本类型变量中 395
27.4.2 使用std::cin:get将输入读取到char数组中 396
27.4.3 使用std::cin将输入读取到std::string中 397
27.5 使用std::fstream处理文件 398
27.5.1 使用open()和close()打开和关闭文件 398
27.5.2 使用open()创建文本文件并使用运算符<<写入文本 399
27.5.3 使用open()和运算符>>读取文本文件 399
27.5.4 读写二进制文件 400
27.6 使用std::stringstream对字符串进行转换 402
27.7 总结 403
27.8 问与答 403
27.9 作业 403
27.9.1 测验 403
27.9.2 练习 404
第 28章 异常处理 405
28.1 什么是异常 405
28.2 导致异常的原因 405
28.3 使用try和catch捕获异常 406
28.3.1 使用catch(...)处理所有异常 406
28.3.2 捕获特定类型的异常 407
28.3.3 使用throw引发特定类型的异常 408
28.4 异常处理的工作原理 409
28.4.1 std::exception类 411
28.4.2 从std::exception派生出自定义异常类 411
28.5 总结 413
28.6 问与答 413
28.7 作业 413
28.7.1 测验 414
28.7.2 练习 414
第 29章 继续前行 415
29.1 当今的处理器有何不同 415
29.2 如何更好地利用多个内核 416
29.2.1 线程是什么 416
29.2.2 为何要编写多线程应用程序 417
29.2.3 线程如何交换数据 417
29.2.4 使用互斥量和信号量同步线程 418
29.2.5 多线程技术带来的问题 418
29.3 编写杰出的C++代码 418
29.4 更深入地学习C++ 419
29.4.1 在线文档 419
29.4.2 提供指南和帮助的社区 420
29.5 总结 420
29.6 问与答 420
29.7 作业 420
附录A 二进制和十六进制 421
A.1 十进制 421
A.2 二进制 421
A.2.1 计算机为何使用二进制 422
A.2.2 位和字节 422
A.2.3 1KB相当于多少字节 422
A.3 十六进制 422
A.4 不同进制之间的转换 423
A.4.1 通用转换步骤 423
A.4.2 从十进制转换为二进制 423
A.4.3 从十进制转换为十六进制 424
附录B C++关键字 425
附录C 运算符优先级 426
附录D 答案 427
附录E ASCII码 456