@@ -80,6 +80,18 @@ std::wstring utf8_to_wstring(std::string const &s) {
8080}
8181```
8282
83+ ## 读取整个文件到字符串
84+
85+ ``` cpp
86+ TODO
87+ ```
88+
89+ ## 位域(bit-field)
90+
91+ ``` cpp
92+ TODO
93+ ```
94+
8395## 别再写构造函数啦!
8496
8597``` cpp
@@ -874,7 +886,7 @@ int res = bound(5, 6); // 等价于 func(6, 1, 5, w);
874886
875887这是一个绑定器,把 `func` 的第二个参数和第四个参数固定下来,形成一个新的函数对象,然后只需要传入前面两个参数就可以调用原来的函数了。
876888
877- 这是一个非常旧的技术,C++11 时代就有了。但是,现在有了 Lambda 表达式,可以更简洁地实现:
889+ 这是一个非常旧的技术,C++98 时代就有了。但是,现在有了 Lambda 表达式,可以更简洁地实现:
878890
879891```cpp
880892int func(int x, int y, int z, int &w);
@@ -898,6 +910,8 @@ Lambda 表达式有许多优势:
898910auto lambda = [&w](int x, int y) { return func(y + 8, 1, x * x, ++w) * 2; };
899911```
900912
913+ ### bind 的历史
914+
901915为什么 C++11 有了 Lambda 表达式,还要提出 `std::bind` 呢?
902916
903917虽然 bind 和 lambda 看似都是在 C++11 引入的,实际上 bind 的提出远远早于 lambda。
@@ -945,6 +959,8 @@ void some_func(int i1, int i2, int i3, int i4);
945959
946960> {{ icon.fun }} 所以,现在还坚持用 bind 的,都是些 2005 年前后在象牙塔接受 C++ 教育,但又不肯“终身学习”的劳保。这批劳保又去“上岸”当“教师”,继续复制 2005 年的错误毒害青少年,实现了劳保的再生产。
947961
962+ ### thread 膝盖中箭
963+
948964糟糕的是,bind 的这种荼毒,甚至影响到了线程库:` std::thread ` 的构造函数就是基于 ` std::bind ` 的!
949965
950966这导致了 ` std::thread ` 和 ` std::bind ` 一样,无法捕获引用。
@@ -975,7 +991,7 @@ t.join();
975991printf("%d\n", x); // 42
976992```
977993
978- 最后再举个绑定随机数生成器例子:
994+ ### 举个绑定随机数生成器例子
979995
980996``` cpp
981997std::mt19937 gen (seed);
@@ -1049,7 +1065,7 @@ void some_func(auto &&arg) {
10491065
10501066少了烦人的尖括号,看起来容易懂多了。
10511067
1052- > {{ icon.tip }} 但是,这里有一个问题 ,为什么 `std::forward` 要写成 `std::forward<T>` 的形式呢?为什么不是 `std::forward(t)` 呢?因为这样写的话,`forward` 也没法知道你的 `t` 是左是右了(函数参数始终会默认推导为左,即使定义的 `t` 是右)因此必须告诉 `forward`,`t` 的定义类型,也就是 `T`,或者通过 `decltype(t)` 来获得 `T`。
1068+ > {{ icon.detail }} 但是,我们同学有一个问题 ,为什么 `std::forward` 要写成 `std::forward<T>` 的形式呢?为什么不是 `std::forward(t)` 呢?因为这样写的话,`forward` 也没法知道你的 `t` 是左是右了(函数参数始终会默认推导为左,即使定义的 `t` 是右)因此必须告诉 `forward`,`t` 的定义类型,也就是 `T`,或者通过 `decltype(t)` 来获得 `T`。
10531069
10541070总之,如果你用的是 `auto &&` 参数,那么 `FWD` 会很方便(自动帮你 `decltype`)。但是如果你用的是模板参数 `T &&`,那么 `FWD` 也可以用,因为 `decltype(t)` 总是得到 `T`。
10551071
@@ -1064,7 +1080,7 @@ struct Class {
10641080 }
10651081
10661082 void hello() {
1067- auto memfn = std::bind(&Class::world, this); // 将 this->world 绑定成一个函数对象
1083+ auto memfn = std::bind(&Class::world, this); // 将 this->world 绑定成一个可以延后调用的函数对象
10681084 memfn();
10691085 memfn();
10701086 }
@@ -1089,7 +1105,7 @@ struct Class {
10891105}
10901106```
10911107
1092- 问题是 ,当我们的成员函数含有多个参数时,bind 就非常麻烦了, 需要一个个写出 placeholder,而且数量必须和 ` world ` 的参数数量一致。每次 ` world ` 要新增参数时,都需要加一下 placeholder,非常沙雕。
1108+ bind 的缺点是 ,当我们的成员函数含有多个参数时,bind 就非常麻烦了: 需要一个个写出 placeholder,而且数量必须和 ` world ` 的参数数量一致。每次 ` world ` 要新增参数时,所有 bind 的地方都需要加一下 placeholder,非常沙雕。
10931109
10941110``` cpp
10951111struct Class {
@@ -1128,7 +1144,7 @@ struct Class {
11281144}
11291145```
11301146
1131- 而 C++14 起 lambda 支持变长参数,就没有这么死板 :
1147+ 而 C++14 起 lambda 支持了变长参数,就不用这么死板 :
11321148
11331149``` cpp
11341150struct Class {
@@ -1150,7 +1166,7 @@ struct Class {
11501166}
11511167```
11521168
1153- 更好的是配合 ` FWD ` 宏实现参数的完美转发:
1169+ 更好的是配合上文提到的 ` FWD ` 宏实现参数的完美转发:
11541170
11551171``` cpp
11561172struct Class {
@@ -1562,28 +1578,10 @@ if (auto it = table.find(key); it != table.end()) {
15621578}
15631579```
15641580
1565- ## 检测是否存在指定成员函数
1566-
1567- TODO
1568-
1569- ## 位域(bit-field)
1570-
15711581## map + any 外挂属性
15721582
1573- ## vector + unordered_map = LRU cache
1574-
1575- ## 多线程通信应基于队列,而不是共享全局变量
1576-
15771583## 自定义 shared_ptr 的 deleter
15781584
1579- ## 读取整个文件
1580-
1581- ## RAII 的 finally
1582-
1583- ## swap 缩小 mutex 区间代价
1584-
1585- ## Lambda 捕获 unique_ptr 导致 function 报错怎么办
1586-
15871585## CHECK_CUDA 类错误检测宏
15881586
15891587## 函数默认参数求值的位置是调用者
@@ -1593,32 +1591,13 @@ TODO
15931591## 花括号实现安全的类型转换检查
15941592
15951593## 成员函数针对 this 的移动重载
1596- ## 位域(bit-field)
1597-
1598- ## vector + unordered_map = LRU cache
1599-
1600- ## 多线程通信应基于队列,而不是共享全局变量
1601-
1602- ## 自定义 shared_ptr 的 deleter
1603-
1604- ## 读取整个文件到字符串
1605-
1606- ## RAII 的 finally
1607-
1608- ## swap 缩小 mutex 区间代价
1609-
1610- ## Lambda 捕获 unique_ptr 导致 function 报错怎么办
16111594
16121595## CHECK_CUDA 类错误检测宏
16131596
16141597## 函数默认参数求值的位置是调用者
16151598
1616- ## 设置 locale 为 .utf8
1617-
16181599## 花括号实现安全的类型转换检查
16191600
1620- ## 成员函数针对 this 的移动重载
1621-
16221601## 临时右值转左值
16231602
16241603C++ 有个特性:支持纯右值(prvalue)隐式转换成 const 的左值引用。
@@ -1671,10 +1650,24 @@ func(temporary(1));
16711650
16721651> {{ icon.story }} 在 Libreoffice 源码中就有应用这个帮手函数。
16731652
1674- ## 临时变量的生命周期是一行
1653+ > {{ icon.warn }} 临时变量的生命周期是一行
16751654
1676- TODO
1655+ ## ADL 机制
1656+
1657+ ## shared_from_this
1658+
1659+ ## requires 语法检测是否存在指定成员函数
16771660
1678- ### ADL 机制
1661+ ## 设置 locale 为 .utf8 解决编码问题
1662+
1663+ ## 成员函数针对 this 的移动重载
16791664
1680- ### `shared_from_this`
1665+ <!-- ## vector + unordered_map = LRU cache -->
1666+ <!-- -->
1667+ <!-- ## Lambda 捕获 unique_ptr 导致 function 报错怎么办 -->
1668+ <!-- -->
1669+ <!-- ## 多线程通信应基于队列,而不是共享全局变量 -->
1670+ <!-- -->
1671+ <!-- ## RAII 的 finally -->
1672+ <!-- -->
1673+ <!-- ## swap 缩小 mutex 区间代价 -->
0 commit comments