mirror of
https://github.com/changkun/modern-cpp-tutorial.git
synced 2025-12-17 20:54:39 +03:00
fix: refine title number
This commit is contained in:
@@ -8,28 +8,9 @@ order: 3
|
||||
|
||||
> 内容修订中
|
||||
|
||||
## 一、本节内容
|
||||
[TOC]
|
||||
|
||||
本节内容包括:
|
||||
|
||||
* 语言运行期的强化
|
||||
* lambda 表达式
|
||||
* lambda 表达式基础
|
||||
* 值捕获
|
||||
* 引用捕获
|
||||
* 隐式捕获
|
||||
* 表达式捕获
|
||||
* 泛型 lambda
|
||||
* 函数对象包装器
|
||||
* std::function
|
||||
* std::bind/std::placeholder
|
||||
* 右值引用
|
||||
* 左值、右值的纯右值、将亡值、右值
|
||||
* 右值引用和左值引用
|
||||
* 移动语义
|
||||
* 完美转发
|
||||
|
||||
## 二、Lambda 表达式
|
||||
## 3.1 Lambda 表达式
|
||||
|
||||
Lambda 表达式是 C++11 中最重要的新特性之一,而 Lambda 表达式,实际上就是提供了一个类似匿名函数的特性,而匿名函数则是在需要一个函数,但是又不想费力去命名一个函数的情况下去使用的。这样的场景其实有很多很多,所以匿名函数几乎是现代编程语言的标配。
|
||||
|
||||
@@ -131,7 +112,7 @@ add(1, 2);
|
||||
add(1.1, 2.2);
|
||||
```
|
||||
|
||||
## 二、函数对象包装器
|
||||
## 3.2 函数对象包装器
|
||||
|
||||
这部分内容虽然属于标准库的一部分,但是从本质上来看,它却增强了 C++ 语言运行时的能力,这部分内容也相当重要,所以放到这里来进行介绍。
|
||||
|
||||
@@ -200,7 +181,7 @@ int main() {
|
||||
|
||||
> **提示:**注意 `auto` 关键字的妙用。有时候我们可能不太熟悉一个函数的返回值类型,但是我们却可以通过 `auto` 的使用来规避这一问题的出现。
|
||||
|
||||
## 三、右值引用
|
||||
## 3.3 右值引用
|
||||
|
||||
右值引用是 C++11 引入的与 Lambda 表达式齐名的重要特性之一。它的引入解决了 C++ 中大量的历史遗留问题,消除了诸如 `std::vector`、`std::string` 之类的额外开销,也才使得函数对象容器 `std::function` 成为了可能。
|
||||
|
||||
|
||||
@@ -8,24 +8,9 @@ order: 4
|
||||
|
||||
> 内容修订中
|
||||
|
||||
## 一、本节内容
|
||||
[TOC]
|
||||
|
||||
本节内容包括:
|
||||
|
||||
* 对标准库的扩充: 新增容器
|
||||
* `std::byte`
|
||||
* `std::any` `std::optional` `std::variant`
|
||||
* `std::string_view`
|
||||
* `std::array`
|
||||
* `std::forward_list`
|
||||
* `std::unordered_set`
|
||||
* `std::unordered_map`
|
||||
* `std::tuple`
|
||||
* 基本操作
|
||||
* 运行期索引
|
||||
* 合并与迭代
|
||||
|
||||
## 二、std::array 和 std::forward\_list
|
||||
## 4.1 std::array 和 std::forward\_list
|
||||
|
||||
### std::array
|
||||
|
||||
@@ -71,7 +56,7 @@ std::sort(arr.begin(), arr.end());
|
||||
|
||||
需要知道的是,和 `std::list` 的双向链表的实现不同,`std::forward_list` 使用单向链表进行实现,提供了 `O(1)` 复杂度的元素插入,不支持快速随机访问(这也是链表的特点),也是标准库容器中唯一一个不提供 `size()` 方法的容器。当不需要双向迭代时,具有比 `std::list` 更高的空间利用率。
|
||||
|
||||
## 三、无序容器
|
||||
## 4.2 无序容器
|
||||
|
||||
我们已经熟知了传统 C++ 中的有序容器 `std::map`/`std::set`,这些元素内部通过红黑树进行实现,插入和搜索的平均复杂度均为 `O(log(size))`。在插入元素时候,会根据 `<` 操作符比较元素大小并判断元素是否相同,并选择合适的位置插入到容器中。当对这个容器中的元素进行遍历时,输出结果会按照 `<` 操作符的顺序来逐个遍历。
|
||||
|
||||
@@ -126,7 +111,7 @@ Key:[2] Value:[2]
|
||||
Key:[3] Value:[3]
|
||||
```
|
||||
|
||||
## 四、元组 std::tuple
|
||||
## 4.3 元组 std::tuple
|
||||
|
||||
了解过 Python 的程序员应该知道元组的概念,纵观传统 C++ 中的容器,除了 `std::pair` 外,似乎没有现成的结构能够用来存放不同类型的数据(通常我们会自己定义结构)。但 `std::pair` 的缺陷是显而易见的,只能保存两个元素。
|
||||
|
||||
|
||||
@@ -8,17 +8,9 @@ order: 5
|
||||
|
||||
> 内容修订中
|
||||
|
||||
## 一、本节内容
|
||||
[TOC]
|
||||
|
||||
本节内容包括:
|
||||
|
||||
- 对标准库的扩充: 智能指针和引用计数
|
||||
+ RAII 与引用计数
|
||||
+ `std::shared_ptr`
|
||||
+ `std::unique_ptr`
|
||||
+ `std::weak_ptr`
|
||||
|
||||
## 二、RAII 与引用计数
|
||||
## 5.1 RAII 与引用计数
|
||||
|
||||
了解 `Objective-C`/`Swift` 的程序员应该知道引用计数的概念。引用计数这种计数是为了防止内存泄露而产生的。基本想法是对于动态分配的对象,进行引用计数,每当增加一次对同一个对象的引用,那么引用对象的引用计数就会增加一次,每删除一次引用,引用计数就会减一,当一个对象的引用计数减为零时,就自动删除指向的堆内存。
|
||||
|
||||
@@ -28,7 +20,7 @@ order: 5
|
||||
|
||||
> 注意:引用计数不是垃圾回收,引用技术能够尽快收回不再被使用的对象,同时在回收的过程中也不会造成长时间的等待,更能够清晰明确的表明资源的生命周期。
|
||||
|
||||
## 三、std::shared_ptr
|
||||
## 5.2 std::shared_ptr
|
||||
|
||||
`std::shared_ptr` 是一种智能指针,它能够记录多少个 `shared_ptr` 共同指向一个对象,从而消除显示的调用 `delete`,当引用计数变为零的时候就会将对象自动删除。
|
||||
|
||||
@@ -78,8 +70,7 @@ std::cout << "pointer2.use_count() = " << pointer2.use_count() << std::endl; //
|
||||
std::cout << "pointer3.use_count() = " << pointer3.use_count() << std::endl; // 0, pointer3 已 reset
|
||||
```
|
||||
|
||||
|
||||
## 四、std::unique_ptr
|
||||
## 5.3 std::unique_ptr
|
||||
|
||||
`std::unique_ptr` 是一种独占的智能指针,它禁止其他智能指针与其共享同一个对象,从而保证代码的安全:
|
||||
|
||||
@@ -138,7 +129,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 五、std::weak_ptr
|
||||
## 5.4 std::weak_ptr
|
||||
|
||||
如果你仔细思考 `std::shared_ptr` 就会发现依然存在着资源无法释放的问题。看下面这个例子:
|
||||
|
||||
|
||||
@@ -8,21 +8,9 @@ order: 6
|
||||
|
||||
> 内容修订中
|
||||
|
||||
## 一、本节内容
|
||||
[TOC]
|
||||
|
||||
本节内容包括:
|
||||
|
||||
- 对标准库的扩充: 正则表达式库
|
||||
+ 正则表达式简介
|
||||
+ 普通字符
|
||||
+ 特殊字符
|
||||
+ 限定符
|
||||
+ `std::regex` 及其相关
|
||||
+ `std::regex`
|
||||
+ `std::regex_match`
|
||||
+ `std::match_results`
|
||||
|
||||
## 二、正则表达式简介
|
||||
## 6.1 正则表达式简介
|
||||
|
||||
正则表达式不是 C++ 语言的一部分,这里仅做简单的介绍。
|
||||
|
||||
@@ -73,7 +61,7 @@ order: 6
|
||||
|
||||
有了这三张表,我们通常就能够读懂几乎所有的正则表达式了。
|
||||
|
||||
## 三、std::regex 及其相关
|
||||
## 6.2 std::regex 及其相关
|
||||
|
||||
对字符串内容进行匹配的最常见手段就是使用正则表达式。可惜在传统 C++ 中正则表达式一直没有得到语言层面的支持,没有纳入标准库,而 C++ 作为一门高性能语言,在后台服务的开发中,对 URL 资源链接进行判断时,使用正则表达式也是工业界最为成熟的普遍做法。
|
||||
|
||||
|
||||
@@ -8,17 +8,9 @@ order: 7
|
||||
|
||||
> 内容修订中
|
||||
|
||||
## 一、本节内容
|
||||
[TOC]
|
||||
|
||||
本节内容包括:
|
||||
|
||||
* 对标准库的扩充: 语言级线程支持
|
||||
* std::thread
|
||||
* std::mutex/std::unique\_lock
|
||||
* std::future/std::packaged\_task
|
||||
* std::condition\_variable
|
||||
|
||||
## 二、std::thread
|
||||
## 7.1 std::thread
|
||||
|
||||
`std::thread` 用于创建一个执行的线程实例,所以它是一切并发编程的基础,使用时需要包含 `<thread>` 头文件,它提供了很多基本的线程操作,例如`get_id()`来获取所创建线程的线程 ID,例如使用 `join()` 来加入一个线程等等,例如:
|
||||
|
||||
@@ -35,7 +27,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 三、 std::mutex, std::unique\_lock
|
||||
## 7.2 std::mutex, std::unique\_lock
|
||||
|
||||
我们在操作系统的相关知识中已经了解过了有关并发技术的基本知识,mutex 就是其中的核心之一。C++11引入了 mutex 相关的类,其所有相关的函数都放在 `<mutex>` 头文件中。
|
||||
|
||||
@@ -88,7 +80,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
#### std::future, std::packaged\_task
|
||||
## 7.3 std::future, std::packaged\_task
|
||||
|
||||
`std::future` 则是提供了一个访问异步操作结果的途径,这句话很不好理解。为了理解这个特性,我们需要先理解一下在 C++11之前的多线程行为。
|
||||
|
||||
@@ -121,7 +113,7 @@ int main()
|
||||
|
||||
在封装好要调用的目标后,可以使用 `get_future()` 来获得一个 `std::future` 对象,以便之后实施线程同步。
|
||||
|
||||
#### std::condition\_variable
|
||||
## 7.4 std::condition_variable
|
||||
|
||||
`std::condition_variable` 是为了解决死锁而生的。当互斥操作不够用而引入的。比如,线程可能需要等待某个条件为真才能继续执行,而一个忙等待循环中可能会导致所有其他线程都无法进入临界区使得条件为真时,就会发生死锁。所以,`condition_variable` 实例被创建出现主要就是用于唤醒等待线程从而避免死锁。`std::condition_variable`的 `notify_one()` 用于唤醒一个线程;`notify_all()` 则是通知所有线程。下面是一个生产者和消费者模型的例子:
|
||||
|
||||
|
||||
@@ -8,25 +8,15 @@ order: 9
|
||||
|
||||
> 内容修订中
|
||||
|
||||
## 一、本节内容
|
||||
[TOC]
|
||||
|
||||
本节内容包括:
|
||||
|
||||
- 对标准库的扩充: 其他杂项
|
||||
+ 新类型
|
||||
+ `long long int`
|
||||
+ `noexcept` 的修饰和操作
|
||||
+ 字面量
|
||||
+ 原始字符串字面量
|
||||
+ 自定义字面量
|
||||
|
||||
## 二、新类型
|
||||
## 9.1 新类型
|
||||
|
||||
### `long long int`
|
||||
|
||||
`long long int` 并不是 C++11 最先引入的,其实早在 C99,`long long int` 就已经被纳入 C 标准中,所以大部分的编译器早已支持。C++11 的工作则是正式把它纳入标准库,规定了一个 `long long int` 类型至少具备 64 位的比特数。
|
||||
|
||||
## 三、noexcept 的修饰和操作
|
||||
## 9.2 noexcept 的修饰和操作
|
||||
|
||||
C++ 相比于 C 的一大优势就在于 C++ 本身就定义了一套完整的异常处理机制。然而在 C++11 之前,几乎没有人去使用在函数名后书写异常声明表达式,从 C++11 开始,这套机制被弃用,所以我们不去讨论也不去介绍以前这套机制是如何工作如何使用,你更不应该主动去了解它。
|
||||
|
||||
@@ -99,7 +89,7 @@ std::cout << "捕获异常, 来自 block_throw()" << std::endl;
|
||||
捕获异常, 来自 non_block_throw()
|
||||
```
|
||||
|
||||
## 四、字面量
|
||||
## 9.3 字面量
|
||||
|
||||
### 原始字符串字面量
|
||||
|
||||
|
||||
@@ -8,21 +8,11 @@ order: 10
|
||||
|
||||
> 内容修订中, 目前内容为第一版中对 C++17 的展望
|
||||
|
||||
## 一、本节内容
|
||||
|
||||
本节内容包括:
|
||||
|
||||
- 扩展主题: C++17 简介
|
||||
+ 主要入选特性
|
||||
+ 非类型模板参数的 `auto`
|
||||
+ `std::variant<>`
|
||||
+ 变量声明的强化
|
||||
+ 未入选特性
|
||||
+ Concepts
|
||||
[TOC]
|
||||
|
||||
本章对即将到来的 C++17 进行介绍,几个月前(2016 年),目前为止,还没有一个正式发布的编译器来编译 C++17 特性的代码,本节作为扩展主题,供对 C++ 的历史进程及其未来发展感兴趣的读者阅读。
|
||||
|
||||
## 二、主要入选特性
|
||||
## 10.1 主要入选特性
|
||||
|
||||
### 非类型模板参数的 auto
|
||||
|
||||
@@ -85,7 +75,7 @@ std::variant<Args...> tuple_index(size_t i, const std::tuple<Args...>& tpl) {
|
||||
|
||||
|
||||
|
||||
## 三、未入选特性
|
||||
## 10.2 未入选特性
|
||||
|
||||
C++ 组委会在讨论投票最终确定 C++17 有很多提案,诸如 **Concepts**/**Ranges**/**Module** 等等,其中最受关注的就是 **Concepts**,可惜这一提案最终被拒,作为技术规范(Technical Specifications, TS) 将其发布。
|
||||
|
||||
@@ -132,7 +122,7 @@ Concepts TS 的发布到最后一次 C++17 的讨论会只相隔了不到四个
|
||||
|
||||
总的来说,类似于 Concepts/Ranges/Modules 这些令人兴奋的特性并没有入选至 C++17,这注定了 C++17 某种意义上来说相较于 C++11/14 依然只是小幅度更新,但我们有望在 C++2x 中看到这些东西的出现,这些内容对于一门已经三十多岁『高龄』的编程语言,依然是充满魅力的。
|
||||
|
||||
[返回目录](./toc.md) | [上一章](./09-others.md) | [下一章 附录:进一步阅读的学习材料](./appendix.md)
|
||||
[返回目录](./toc.md) | [上一章](./09-others.md) | [下一章 附录:进一步阅读的学习材料](./appendix1.md)
|
||||
|
||||
|
||||
## 进一步阅读的参考资料
|
||||
|
||||
Reference in New Issue
Block a user