248
248
< ul class ="nav flex-column ">
249
249
</ ul >
250
250
</ li >
251
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#raii " class ="nav-link "> RAII 地分配一段内存空间 </ a >
251
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_2 " class ="nav-link "> 安全地分配一段内存空间 </ a >
252
252
< ul class ="nav flex-column ">
253
253
</ ul >
254
254
</ li >
255
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_2 " class ="nav-link "> 读取整个文件到字符串 </ a >
255
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_3 " class ="nav-link "> 地板除与天花板除 </ a >
256
256
< ul class ="nav flex-column ">
257
257
</ ul >
258
258
</ li >
259
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_3 " class ="nav-link "> 别再写构造函数啦! </ a >
259
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_4 " class ="nav-link "> 读取整个文件到字符串 </ a >
260
260
< ul class ="nav flex-column ">
261
261
</ ul >
262
262
</ li >
263
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_4 " class ="nav-link "> 别再写拷贝构造函数啦 !</ a >
263
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_5 " class ="nav-link "> 别再写构造函数啦 !</ a >
264
264
< ul class ="nav flex-column ">
265
265
</ ul >
266
266
</ li >
267
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_5 " class ="nav-link "> 提前返回</ a >
267
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_6 " class ="nav-link "> 别再写拷贝构造函数啦!</ a >
268
+ < ul class ="nav flex-column ">
269
+ </ ul >
270
+ </ li >
271
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_7 " class ="nav-link "> 提前返回</ a >
268
272
< ul class ="nav flex-column ">
269
273
</ ul >
270
274
</ li >
280
284
< ul class ="nav flex-column ">
281
285
</ ul >
282
286
</ li >
283
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_6 " class ="nav-link "> 别再 [] 啦!</ a >
287
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_8 " class ="nav-link "> 别再 [] 啦!</ a >
284
288
< ul class ="nav flex-column ">
285
289
</ ul >
286
290
</ li >
332
336
< ul class ="nav flex-column ">
333
337
</ ul >
334
338
</ li >
335
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_7 " class ="nav-link "> 智能指针防止大对象移动</ a >
339
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_9 " class ="nav-link "> 智能指针防止大对象移动</ a >
336
340
< ul class ="nav flex-column ">
337
341
</ ul >
338
342
</ li >
356
360
< ul class ="nav flex-column ">
357
361
</ ul >
358
362
</ li >
359
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_9 " class ="nav-link "> 救命!为什么我的全局函数不能作为函数对象?</ a >
363
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_11 " class ="nav-link "> 救命!为什么我的全局函数不能作为函数对象?</ a >
360
364
< ul class ="nav flex-column ">
361
365
</ ul >
362
366
</ li >
372
376
< ul class ="nav flex-column ">
373
377
</ ul >
374
378
</ li >
375
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_10 " class ="nav-link "> 函数默认参数求值的位置是调用者</ a >
379
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_12 " class ="nav-link "> 函数默认参数求值的位置是调用者</ a >
376
380
< ul class ="nav flex-column ">
377
381
</ ul >
378
382
</ li >
379
383
< li class ="nav-item " data-bs-level ="2 "> < a href ="#locale-utf8 " class ="nav-link "> 设置 locale 为 .utf8</ a >
380
384
< ul class ="nav flex-column ">
381
385
</ ul >
382
386
</ li >
383
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_11 " class ="nav-link "> 花括号实现安全的类型转换检查</ a >
387
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_13 " class ="nav-link "> 花括号实现安全的类型转换检查</ a >
384
388
< ul class ="nav flex-column ">
385
389
</ ul >
386
390
</ li >
392
396
< ul class ="nav flex-column ">
393
397
</ ul >
394
398
</ li >
395
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_12 " class ="nav-link "> 函数默认参数求值的位置是调用者</ a >
399
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_14 " class ="nav-link "> 函数默认参数求值的位置是调用者</ a >
396
400
< ul class ="nav flex-column ">
397
401
</ ul >
398
402
</ li >
399
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_13 " class ="nav-link "> 花括号实现安全的类型转换检查</ a >
403
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_15 " class ="nav-link "> 花括号实现安全的类型转换检查</ a >
400
404
< ul class ="nav flex-column ">
401
405
</ ul >
402
406
</ li >
403
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_14 " class ="nav-link "> 临时右值转左值</ a >
407
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_16 " class ="nav-link "> 临时右值转左值</ a >
404
408
< ul class ="nav flex-column ">
405
409
</ ul >
406
410
</ li >
440
444
< ul class ="nav flex-column ">
441
445
</ ul >
442
446
</ li >
443
- < li class ="nav-item " data-bs-level ="2 "> < a href ="#_15 " class ="nav-link "> 多线程通信应基于队列,而不是共享全局变量</ a >
447
+ < li class ="nav-item " data-bs-level ="2 "> < a href ="#_17 " class ="nav-link "> 多线程通信应基于队列,而不是共享全局变量</ a >
444
448
< ul class ="nav flex-column ">
445
449
</ ul >
446
450
</ li >
@@ -464,15 +468,16 @@ <h1 id="c">应知应会 C++ 小技巧</h1>
464
468
< ul >
465
469
< li > < a href ="#c "> 应知应会 C++ 小技巧</ a > < ul >
466
470
< li > < a href ="#_1 "> 交换两个变量</ a > </ li >
467
- < li > < a href ="#raii "> RAII 地分配一段内存空间</ a > </ li >
468
- < li > < a href ="#_2 "> 读取整个文件到字符串</ a > </ li >
469
- < li > < a href ="#_3 "> 别再写构造函数啦!</ a > </ li >
470
- < li > < a href ="#_4 "> 别再写拷贝构造函数啦!</ a > </ li >
471
- < li > < a href ="#_5 "> 提前返回</ a > </ li >
471
+ < li > < a href ="#_2 "> 安全地分配一段内存空间</ a > </ li >
472
+ < li > < a href ="#_3 "> 地板除与天花板除</ a > </ li >
473
+ < li > < a href ="#_4 "> 读取整个文件到字符串</ a > </ li >
474
+ < li > < a href ="#_5 "> 别再写构造函数啦!</ a > </ li >
475
+ < li > < a href ="#_6 "> 别再写拷贝构造函数啦!</ a > </ li >
476
+ < li > < a href ="#_7 "> 提前返回</ a > </ li >
472
477
< li > < a href ="#lambda "> 立即调用的 Lambda</ a > </ li >
473
478
< li > < a href ="#lambda_1 "> Lambda 复用代码</ a > </ li >
474
479
< li > < a href ="#inline "> 类内静态成员 inline</ a > </ li >
475
- < li > < a href ="#_6 "> 别再 [] 啦!</ a > </ li >
480
+ < li > < a href ="#_8 "> 别再 [] 啦!</ a > </ li >
476
481
< li > < a href ="#make_pair "> 别再 make_pair 啦!</ a > </ li >
477
482
< li > < a href ="#insert "> insert 不会替换现有值哦</ a > </ li >
478
483
< li > < a href ="#map "> 一边遍历 map,一边删除?</ a > </ li >
@@ -485,29 +490,29 @@ <h1 id="c">应知应会 C++ 小技巧</h1>
485
490
< li > < a href ="#cout-endl "> cout 不需要 endl</ a > </ li >
486
491
< li > < a href ="#cout "> 多线程中 cout 出现乱序?</ a > </ li >
487
492
< li > < a href ="#cerr-cout "> cerr 与 cout 的抉择</ a > </ li >
488
- < li > < a href ="#_7 "> 智能指针防止大对象移动</ a > </ li >
493
+ < li > < a href ="#_9 "> 智能指针防止大对象移动</ a > </ li >
489
494
< li > < a href ="#optional "> optional 实现延迟初始化</ a > </ li >
490
495
< li > < a href ="#if-auto-while-auto "> if-auto 与 while-auto</ a > </ li >
491
496
< li > < a href ="#bind-lambda "> bind 是历史糟粕,应该由 Lambda 表达式取代</ a > < ul >
492
497
< li > < a href ="#bind "> bind 的历史</ a > </ li >
493
498
< li > < a href ="#thread "> thread 膝盖中箭</ a > </ li >
494
- < li > < a href ="#_8 "> 举个绑定随机数生成器例子</ a > </ li >
499
+ < li > < a href ="#_10 "> 举个绑定随机数生成器例子</ a > </ li >
495
500
</ ul >
496
501
</ li >
497
502
< li > < a href ="#forward-fwd "> forward 迷惑性地不好用,建议改用 FWD 宏</ a > </ li >
498
503
< li > < a href ="#bind-lambda-bind_front "> bind 绑定成员函数是陋习,改用 lambda 或 bind_front</ a > </ li >
499
- < li > < a href ="#_9 "> 救命!为什么我的全局函数不能作为函数对象?</ a > </ li >
504
+ < li > < a href ="#_11 "> 救命!为什么我的全局函数不能作为函数对象?</ a > </ li >
500
505
< li > < a href ="#map-any "> map + any 外挂属性</ a > </ li >
501
506
< li > < a href ="#shared_ptr-deleter "> 自定义 shared_ptr 的 deleter</ a > </ li >
502
507
< li > < a href ="#check_cuda "> CHECK_CUDA 类错误检测宏</ a > </ li >
503
- < li > < a href ="#_10 "> 函数默认参数求值的位置是调用者</ a > </ li >
508
+ < li > < a href ="#_12 "> 函数默认参数求值的位置是调用者</ a > </ li >
504
509
< li > < a href ="#locale-utf8 "> 设置 locale 为 .utf8</ a > </ li >
505
- < li > < a href ="#_11 "> 花括号实现安全的类型转换检查</ a > </ li >
510
+ < li > < a href ="#_13 "> 花括号实现安全的类型转换检查</ a > </ li >
506
511
< li > < a href ="#this "> 成员函数针对 this 的移动重载</ a > </ li >
507
512
< li > < a href ="#check_cuda_1 "> CHECK_CUDA 类错误检测宏</ a > </ li >
508
- < li > < a href ="#_12 "> 函数默认参数求值的位置是调用者</ a > </ li >
509
- < li > < a href ="#_13 "> 花括号实现安全的类型转换检查</ a > </ li >
510
- < li > < a href ="#_14 "> 临时右值转左值</ a > </ li >
513
+ < li > < a href ="#_14 "> 函数默认参数求值的位置是调用者</ a > </ li >
514
+ < li > < a href ="#_15 "> 花括号实现安全的类型转换检查</ a > </ li >
515
+ < li > < a href ="#_16 "> 临时右值转左值</ a > </ li >
511
516
< li > < a href ="#ostringstream "> ostringstream 格式化字符串</ a > </ li >
512
517
< li > < a href ="#adl "> ADL 机制实现静态多态</ a > </ li >
513
518
< li > < a href ="#shared_from_this "> shared_from_this</ a > </ li >
@@ -517,7 +522,7 @@ <h1 id="c">应知应会 C++ 小技巧</h1>
517
522
< li > < a href ="#bit-field "> 位域(bit-field)</ a > </ li >
518
523
< li > < a href ="#vector-unordered_map-lru-cache "> vector + unordered_map = LRU cache</ a > </ li >
519
524
< li > < a href ="#lambda-unique_ptr-function "> Lambda 捕获 unique_ptr 导致 function 报错怎么办</ a > </ li >
520
- < li > < a href ="#_15 "> 多线程通信应基于队列,而不是共享全局变量</ a > </ li >
525
+ < li > < a href ="#_17 "> 多线程通信应基于队列,而不是共享全局变量</ a > </ li >
521
526
< li > < a href ="#raii-finally "> RAII 的 finally</ a > </ li >
522
527
< li > < a href ="#swap-mutex "> swap 缩小 mutex 区间代价</ a > </ li >
523
528
</ ul >
@@ -540,8 +545,8 @@ <h2 id="_1">交换两个变量</h2>
540
545
< blockquote >
541
546
< p > < img src ="../img/bulb.png " height ="30px " width ="auto " style ="margin: 0; border: none "/> 只需要 < code > #include <utility></ code > 就可以使用!</ p >
542
547
</ blockquote >
543
- < h2 id ="raii " > RAII 地分配一段内存空间 </ h2 >
544
- < p > 小彭老师:不要让我看到 new 和 delete。</ p >
548
+ < h2 id ="_2 " > 安全地分配一段内存空间 </ h2 >
549
+ < p > 小彭老师:不要出现 new 和 delete,不安全 。</ p >
545
550
< p > 同学:我想要< strong > 分配一段内存空间</ strong > ,你不让我 new,我还能怎么办呢?</ p >
546
551
< pre > < code class ="language-cpp "> char *mem = new char[1024]; // 同学想要 1024 字节的缓冲区
547
552
read(1, mem, 1024); // 用于供 C 语言的读文件函数使用
@@ -579,7 +584,37 @@ <h2 id="raii">RAII 地分配一段内存空间</h2>
579
584
return ws;
580
585
}
581
586
</ code > </ pre >
582
- < h2 id ="_2 "> 读取整个文件到字符串</ h2 >
587
+ < h2 id ="_3 "> 地板除与天花板除</ h2 >
588
+ < p > 众所周知,C语言中 < code > int</ code > 相除 < code > /</ code > ,得到的结果也是 < code > int</ code > ,如果除法产生了余数,那么只会保留整数部分。</ p >
589
+ < p > 例如 < code > 14 / 5</ code > ,本来应该得到 2.8。但是因为 C 语言的除法返回 < code > int</ code > ,结果会自动向下取整,导致得到 2。</ p >
590
+ < pre > < code class ="language-cpp "> int a, b;
591
+ int c = a / b;
592
+ </ code > </ pre >
593
+ < p > 等价于</ p >
594
+ < pre > < code class ="language-cpp "> int c = floor((float)a / b);
595
+ </ code > </ pre >
596
+ < p > 如果 < code > a</ code > 除以 < code > b</ code > 除不尽,那么会找到比他大的第一个整数作为结果,这就是< strong > 地板除 (floor div)</ strong > 。</ p >
597
+ < p > C 语言默认的就是地板除。</ p >
598
+ < p > 如果我想要的是向上取整,该怎么写?</ p >
599
+ < p > 最原始的写法是先转成浮点数来除,然后ceil函数向上取整:</ p >
600
+ < pre > < code class ="language-cpp "> int c = ceil((float)a / b);
601
+ </ code > </ pre >
602
+ < p > 但是浮点数不仅低效,还有糟糕的浮点数精度误差!对于很大的整数(大于 < span class ="arithmatex "> < span class ="MathJax_Preview "> 2^{23}</ span > < script type ="math/tex "> 2 ^ { 23 } </ script > </ span > )会产生错误的结果。</ p >
603
+ < p > 更合理的写法是先把 < code > a</ code > 加上 < code > b - 1</ code > ,然后再下取整地除以 < code > b</ code > :</ p >
604
+ < pre > < code class ="language-cpp "> int c = (a + b - 1) / b;
605
+ </ code > </ pre >
606
+ < p > 这样就能产生一个向上取整的除法了。</ p >
607
+ < p > 如果 < code > a</ code > 除以 < code > b</ code > 除不尽,那么会找到比他大的第一个整数作为结果,这就是< strong > 天花板除 (ceil div)</ strong > 。</ p >
608
+ < p > 试试看:14 除以 5,应该得到 2.8;如果用地板除,会得到 2;如果用天花板除,会得到 3。</ p >
609
+ < pre > < code class ="language-cpp "> 14 / 5 = 2
610
+ (14 + 5 - 1) / 5 = (14 + 4) / 5 = 18 / 5 = 3
611
+ </ code > </ pre >
612
+ < p > 试试看:10 除以 5,应该得到 2;那么无论是地板除还是天花板除,都应该得到 2。</ p >
613
+ < pre > < code class ="language-cpp "> 10 / 5 = 2
614
+ (10 + 5 - 1) / 5 = (10 + 4) / 5 = 14 / 5 = 2
615
+ </ code > </ pre >
616
+ < p > 这就是 C 语言中实现天花板除的业界公认标准方式。</ p >
617
+ < h2 id ="_4 "> 读取整个文件到字符串</ h2 >
583
618
< pre > < code class ="language-cpp "> std::string file_get_content(std::string const &filename) {
584
619
std::ifstream ifs(filename, std::ios::in | std::ios::binary);
585
620
std::istreambuf_iterator<char> iit(ifs), iite;
@@ -596,7 +631,7 @@ <h2 id="_2">读取整个文件到字符串</h2>
596
631
< blockquote >
597
632
< p > < img src ="../img/bulb.png " height ="30px " width ="auto " style ="margin: 0; border: none "/> 推荐用 < code > std::ios::binary</ code > 选项打开二进制文件,否则字符串中出现 < code > '\n'</ code > 时,会被 MSVC 标准库自动转换成 < code > '\r\n'</ code > 来写入,妨碍我们跨平台。</ p >
598
633
</ blockquote >
599
- < h2 id ="_3 "> 别再写构造函数啦!</ h2 >
634
+ < h2 id ="_5 "> 别再写构造函数啦!</ h2 >
600
635
< pre > < code class ="language-cpp "> // C++98
601
636
struct Student {
602
637
string name;
@@ -619,7 +654,7 @@ <h2 id="_3">别再写构造函数啦!</h2>
619
654
620
655
Student stu{"小彭老师", 24, 123};
621
656
</ code > </ pre >
622
- < p > 这被称为< strong > 聚合初始化</ strong > (aggergate initialize)。只要你的类没有自定义构造函数,没有 private 成员,都可以用 < code > {}</ code > 聚合初始化。</ p >
657
+ < p > 这被称为< strong > 聚合初始化</ strong > (aggregate initialize)。只要你的类没有自定义构造函数,没有 private 成员,都可以用 < code > {}</ code > 聚合初始化。</ p >
623
658
< p > 好消息:C++20 中,聚合初始化也支持 < code > ()</ code > 了,用起来就和传统的 C++98 构造函数一样!</ p >
624
659
< pre > < code class ="language-cpp "> // C++20
625
660
Student stu("小彭老师", 24, 123);
@@ -645,7 +680,7 @@ <h2 id="_3">别再写构造函数啦!</h2>
645
680
< pre > < code class ="language-cpp "> Student stu{.name = "小彭老师", .age = 24, .id = 9999};
646
681
Student stu{.name = "小彭老师", .id = 9999, .age = 24};
647
682
</ code > </ pre >
648
- < h2 id ="_4 "> 别再写拷贝构造函数啦!</ h2 >
683
+ < h2 id ="_6 "> 别再写拷贝构造函数啦!</ h2 >
649
684
< p > 只有当你需要有“自定义钩子逻辑”的时候,才需要自定义构造函数。</ p >
650
685
< pre > < code class ="language-cpp "> struct Student {
651
686
string name;
@@ -691,7 +726,7 @@ <h2 id="_4">别再写拷贝构造函数啦!</h2>
691
726
< p > 总之,很多 C++ 教材把拷贝/移动构造函数过于夸大,搞得好像每个类都需要自己定义一样。</ p >
692
727
< p > 实际上,只有在“自己实现容器”的情况下,才需要自定义拷贝构造函数。可是谁会整天手搓容器?</ p >
693
728
< p > 大多数情况下,我们只需要在类里面存 vector、string 等封装好的容器,编译器默认生成的拷贝构造函数会自动调用他们的拷贝构造函数,用户只需专注于业务逻辑即可,不需要操心底层细节。</ p >
694
- < h2 id ="_5 "> 提前返回</ h2 >
729
+ < h2 id ="_7 "> 提前返回</ h2 >
695
730
< pre > < code class ="language-cpp "> void babysitter(Baby *baby) {
696
731
if (!baby->is_alive()) {
697
732
puts("宝宝已经去世了");
@@ -796,7 +831,7 @@ <h2 id="inline">类内静态成员 inline</h2>
796
831
inline static int member;
797
832
};
798
833
</ code > </ pre >
799
- < h2 id ="_6 "> 别再 < code > []</ code > 啦!</ h2 >
834
+ < h2 id ="_8 "> 别再 < code > []</ code > 啦!</ h2 >
800
835
< p > 你知道吗?在 map 中使用 < code > []</ code > 查找元素,如果不存在,会自动创建一个默认值。这个特性有时很方便,但如果你不小心写错了,就会在 map 中创建一个多余的默认元素。</ p >
801
836
< pre > < code class ="language-cpp "> map<string, int> table;
802
837
table["小彭老师"] = 24;
@@ -1249,7 +1284,7 @@ <h2 id="cerr-cout">cerr 与 cout 的抉择</h2>
1249
1284
1 3 5 7
1250
1285
11 13 17 19
1251
1286
</ code > </ pre >
1252
- < h2 id ="_7 "> 智能指针防止大对象移动</ h2 >
1287
+ < h2 id ="_9 "> 智能指针防止大对象移动</ h2 >
1253
1288
< p > 我们说一个类型大,有两种情况。</ p >
1254
1289
< ol >
1255
1290
< li > 类本身很大:例如 array</ li >
@@ -1527,7 +1562,7 @@ <h3 id="thread">thread 膝盖中箭</h3>
1527
1562
t.join();
1528
1563
printf("%d\n", x); // 42
1529
1564
</ code > </ pre >
1530
- < h3 id ="_8 "> 举个绑定随机数生成器例子</ h3 >
1565
+ < h3 id ="_10 "> 举个绑定随机数生成器例子</ h3 >
1531
1566
< p > bind 写法:</ p >
1532
1567
< pre > < code class ="language-cpp "> std::mt19937 gen(seed);
1533
1568
std::uniform_real_distribution<double> uni(0, 1);
@@ -1739,7 +1774,7 @@ <h2 id="bind-lambda-bind_front">bind 绑定成员函数是陋习,改用 lambda
1739
1774
auto memfn = BIND(world, this); // 小彭老师的 BIND 宏,C++14 起可用
1740
1775
</ code > </ pre >
1741
1776
< p > 你更喜欢哪一种呢?</ p >
1742
- < h2 id ="_9 "> 救命!为什么我的全局函数不能作为函数对象?</ h2 >
1777
+ < h2 id ="_11 "> 救命!为什么我的全局函数不能作为函数对象?</ h2 >
1743
1778
< p > 当你的全局函数是模板函数,或带有重载的函数时:</ p >
1744
1779
< pre > < code class ="language-cpp "> template <class T>
1745
1780
T square(T const t) {
@@ -1811,14 +1846,14 @@ <h2 id="map-any">map + any 外挂属性</h2>
1811
1846
< p > TODO</ p >
1812
1847
< h2 id ="shared_ptr-deleter "> 自定义 shared_ptr 的 deleter</ h2 >
1813
1848
< h2 id ="check_cuda "> CHECK_CUDA 类错误检测宏</ h2 >
1814
- < h2 id ="_10 "> 函数默认参数求值的位置是调用者</ h2 >
1849
+ < h2 id ="_12 "> 函数默认参数求值的位置是调用者</ h2 >
1815
1850
< h2 id ="locale-utf8 "> 设置 locale 为 .utf8</ h2 >
1816
- < h2 id ="_11 "> 花括号实现安全的类型转换检查</ h2 >
1851
+ < h2 id ="_13 "> 花括号实现安全的类型转换检查</ h2 >
1817
1852
< h2 id ="this "> 成员函数针对 this 的移动重载</ h2 >
1818
1853
< h2 id ="check_cuda_1 "> CHECK_CUDA 类错误检测宏</ h2 >
1819
- < h2 id ="_12 "> 函数默认参数求值的位置是调用者</ h2 >
1820
- < h2 id ="_13 "> 花括号实现安全的类型转换检查</ h2 >
1821
- < h2 id ="_14 "> 临时右值转左值</ h2 >
1854
+ < h2 id ="_14 "> 函数默认参数求值的位置是调用者</ h2 >
1855
+ < h2 id ="_15 "> 花括号实现安全的类型转换检查</ h2 >
1856
+ < h2 id ="_16 "> 临时右值转左值</ h2 >
1822
1857
< p > C++ 有个特性:支持纯右值(prvalue)隐式转换成 const 的左值引用。</ p >
1823
1858
< p > 翻译:< code > int &&</ code > 可以自动转换成 < code > int const &</ code > 。</ p >
1824
1859
< pre > < code class ="language-cpp "> void func(int const &i);
@@ -1903,7 +1938,7 @@ <h2 id="bit-field">位域(bit-field)</h2>
1903
1938
</ code > </ pre >
1904
1939
< h2 id ="vector-unordered_map-lru-cache "> vector + unordered_map = LRU cache</ h2 >
1905
1940
< h2 id ="lambda-unique_ptr-function "> Lambda 捕获 unique_ptr 导致 function 报错怎么办</ h2 >
1906
- < h2 id ="_15 "> 多线程通信应基于队列,而不是共享全局变量</ h2 >
1941
+ < h2 id ="_17 "> 多线程通信应基于队列,而不是共享全局变量</ h2 >
1907
1942
< h2 id ="raii-finally "> RAII 的 finally</ h2 >
1908
1943
< h2 id ="swap-mutex "> swap 缩小 mutex 区间代价</ h2 > </ div >
1909
1944
</ div >
0 commit comments