-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.xml
More file actions
2352 lines (2343 loc) · 293 KB
/
index.xml
File metadata and controls
2352 lines (2343 loc) · 293 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>水阙</title><link>https://guyueshui.github.io/</link><description>Recent content on 水阙</description><generator>Hugo</generator><language>en</language><lastBuildDate>Wed, 25 Mar 2026 14:01:30 +0800</lastBuildDate><atom:link href="https://guyueshui.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>Texlive 精简安装</title><link>https://guyueshui.github.io/post/texlive-clean-install/</link><pubDate>Tue, 24 Mar 2026 22:30:28 +0800</pubDate><guid>https://guyueshui.github.io/post/texlive-clean-install/</guid><description><p>时隔多年,竟然需要再次安装 Texlive 了。上一次装还是上学那会儿,在中科大镜像网站下载 texlive-xxxx.iso,挂载到本地进行安装。当时就是完全安装,也不知道哪个可以不装,不装会否影响使用等等。所以一股脑全量安装,装完大概占用小 10GB 空间吧,还是很重量级的!好在前段时间搜索教程发现可以精简安装,遂决定动手试试。</p></description></item><item><title>网上冲浪的意义</title><link>https://guyueshui.github.io/post/meaning-of-surfing/</link><pubDate>Wed, 18 Mar 2026 13:23:50 +0800</pubDate><guid>https://guyueshui.github.io/post/meaning-of-surfing/</guid><description><p>我们上网的意义到底是什么?</p></description></item><item><title>析构函数与 override</title><link>https://guyueshui.github.io/post/override-destructor/</link><pubDate>Wed, 03 Sep 2025 21:40:03 +0800</pubDate><guid>https://guyueshui.github.io/post/override-destructor/</guid><description><ul>
<li><code>virtual</code></li>
<li><code>override</code></li>
<li><code>final</code></li>
</ul>
<p>上面三个关键字在继承体系中起着重要作用。<code>virtual</code>不用多说,声明虚函数必备的关键字。<code>override</code>和<code>final</code>是 C++11 中引入的,二者的作用其实更多是提醒开发者自己,</p>
<ul>
<li>我正在重写一个虚函数</li>
<li>我正在重写一个虚函数,并且不希望再被派生类重写这个函数</li>
</ul></description></item><item><title>遇见 ChiliChill</title><link>https://guyueshui.github.io/post/met-chilichill/</link><pubDate>Fri, 18 Apr 2025 21:27:03 +0800</pubDate><guid>https://guyueshui.github.io/post/met-chilichill/</guid><description><p>“世界上有两种人,一种是喜欢 ChiliChill 的,一种是还没听过 ChiliChill 的。”</p>
<p><img src="https://guyueshui.github.io/img/posted/chilichill.png" style="width: 60%;"></img>
<div class='align-center' style="font-size:smaller; font-family: serif; margin-top: -0.5em">
logo
</div></p></description></item><item><title>痛的少一些!Windows</title><link>https://guyueshui.github.io/post/suckless-windows/</link><pubDate>Wed, 08 Jan 2025 20:36:52 +0800</pubDate><guid>https://guyueshui.github.io/post/suckless-windows/</guid><description><p>Windows 痛点例举,</p>
<ul>
<li>祖传蓝屏(这一点在 XP 上尤为严重,Win7 以上已经少见许多)。</li>
<li>静默更新。悄悄下载更新,强制更新,莫名其妙跳出来说要更新,关机时强迫更新。恶心的默认策略!</li>
<li>万年难用的资源管理器,不带标签页,窗口开一堆。</li>
<li>开发上来说,编译工具链体验比不上 linux.</li>
</ul>
<p>虽然 Windows 很难用,但并不妨碍它桌面市场占用率第一的地位。在生活或者工作中,我还是无法避免地被动使用 windows. 因此,我希望通过一些简单定制,让我的使用体验能好一些。</p></description></item><item><title>Android 手机备份攻略</title><link>https://guyueshui.github.io/post/android-backup/</link><pubDate>Tue, 26 Mar 2024 22:33:43 +0800</pubDate><guid>https://guyueshui.github.io/post/android-backup/</guid><description><p>说起 Android 手机的备份,最先闯入眼帘的可能是 XX 搬机助手,某某手机搬家等一键式迁移手机数据的 APP,这些 APP 可以迁移的数据包括,联系人、通话记录、短信、应用(不包括应用数据)、照片视频、文件夹等,此外还包括一些系统设置例如 WIFI 密码<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p></description></item><item><title>黑山小妖</title><link>https://guyueshui.github.io/post/%E9%BB%91%E5%B1%B1%E5%B0%8F%E5%A6%96/</link><pubDate>Fri, 10 Nov 2023 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/%E9%BB%91%E5%B1%B1%E5%B0%8F%E5%A6%96/</guid><description><p>今天来说说女儿睡觉的事。女儿十三个多月了,自从五六个月的时候给她一个人睡摇篮,她就能从晚上八九点睡到第二天早上六七点。就这样过了几个月,我在外上班,平时她妈妈带她睡。忽然有段时间,妻子说不舍得她一个人睡,又开始把她抱到床上睡。就这样又过了一段时间。</p></description></item><item><title>护眼显示器选购指南</title><link>https://guyueshui.github.io/post/eye-comfortable-displayer/</link><pubDate>Wed, 14 Jun 2023 19:56:54 +0800</pubDate><guid>https://guyueshui.github.io/post/eye-comfortable-displayer/</guid><description><p>常年对着破旧笔记本的粗糙小屏幕,实在是对不起自己的眼睛。这不,趁着今年 618 打算买个显示器。预算 1500,分辨率 2K 起,要求具备莱茵低蓝光认证。</p></description></item><item><title>从零开始构建家庭共享存储</title><link>https://guyueshui.github.io/post/share-storage-with-family/</link><pubDate>Tue, 14 Mar 2023 09:24:57 +0800</pubDate><guid>https://guyueshui.github.io/post/share-storage-with-family/</guid><description><p>一切都要从前几天给手机刷新 ROM,导致数据丢失说起。</p>
<p>前些日子,我的 RedmiK40S MIUI13 突然给我自动更新至 MIUI14,这违背了我的意愿。但这还不至于让我动刷机的年头,毕竟年事已高,不再那么想折腾手机。可这次更新,不单单是 MIUI 版本的提升,更是 Android 12 到 13 的版本升级。这直接导致了我的钛备份闪退了,并且使用钛备份还原在 a12 上备份的应用,如果勾选还原应用数据,则必然导致对应应用闪退。应用备份出了问题我是无法接受的。于是,开始上 XDA 找 ROM,随便下了几个,准备动手。</p></description></item><item><title>Swap 扩容</title><link>https://guyueshui.github.io/post/extend-swap/</link><pubDate>Fri, 24 Feb 2023 21:07:16 +0800</pubDate><guid>https://guyueshui.github.io/post/extend-swap/</guid><description><!--
由于涉及到磁盘分区,一般来说 swap 分区在安装系统的时候就要确定。一般建议为总内存大小的一半。
可以通过如下步骤设置一个 swap 分区:
```bash
mkswap /dev/swap_partition
swapon /dev/swap_partition
```
-->
<p>先前安装系统的时候,swap 分区给小了(机器内存的一半)。我的笔记本内存 8G,swap 给了 4G,当系统已用内存超过 4G,会导致无法<a href="https://guyueshui.github.io/post/linux-hibernate#%E7%A1%AE%E4%BF%9Dswap%E5%88%86%E5%8C%BA%E8%B6%B3%E5%A4%9F%E5%A4%A7">休眠</a>。如果 swap 给的和本机内存一样大,那么就不会存在 swap 放不下当前工作镜像的问题。但重新分区追加 swap 显然不现实,所以只能让两块 swap 拼凑一下,达到总体有 8G 可用 swap 的效果。</p></description></item><item><title>喜女</title><link>https://guyueshui.github.io/post/birth-of-shang/</link><pubDate>Sun, 06 Nov 2022 19:00:00 +0800</pubDate><guid>https://guyueshui.github.io/post/birth-of-shang/</guid><description><p>壬寅年九月,喜得一女,因作此篇。</p>
<p>九月孕明珠,</p>
<p>玲珑宛天成。</p>
<p>愿织锦绣梦,</p>
<p>携手度余生。</p></description></item><item><title>C++ 中的默认参数简介</title><link>https://guyueshui.github.io/post/cpp-default-argument/</link><pubDate>Wed, 14 Sep 2022 13:23:39 +0800</pubDate><guid>https://guyueshui.github.io/post/cpp-default-argument/</guid><description><h2 id="minimal-example">Minimal example</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">foo</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">foo</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> <span class="c1">// call foo(5, 1)
</span></span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="分离编译带来的隐患">分离编译带来的隐患</h2>
<p>如果函数声明和定义分离,此时就有一个 pitfall。由于默认参数可以定义在函数声明(declaration)中,也可以定义在函数定义(definition)中。</p></description></item><item><title>红米 K40S 初体验</title><link>https://guyueshui.github.io/post/fresh-experience-on-munch/</link><pubDate>Tue, 13 Sep 2022 21:42:54 +0800</pubDate><guid>https://guyueshui.github.io/post/fresh-experience-on-munch/</guid><description><p>8 月 8 日入手了一台红米 K40S(设备代号 munch)。蹲了很久了,终于等到 88 购物节一波降价,在某东 1999 拿下顶配版 K40S.</p></description></item><item><title>C++ 中的 static 关键字</title><link>https://guyueshui.github.io/post/static-in-cpp/</link><pubDate>Thu, 21 Apr 2022 23:52:04 +0800</pubDate><guid>https://guyueshui.github.io/post/static-in-cpp/</guid><description><h2 id="static-members">Static members</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-c++" data-lang="c++"><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">A</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// non-static member (i.e., `data` is not visible in `fun1`
</span></span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="n">fun1</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> <span class="n">fun2</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">data</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="kt">int</span> <span class="n">sata</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">A</span> <span class="n">a</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">a</span><span class="p">.</span><span class="n">fun1</span><span class="p">();</span> <span class="c1">// valid, equivalent to the following
</span></span></span><span class="line"><span class="cl"><span class="n">A</span><span class="o">::</span><span class="n">fun1</span><span class="p">();</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ol>
<li>静态成员不能访问非静态成员(因为静态成员独立与类的实例(即对象)而存在,为了在没有对象被创建的情况下,静态成员还是可以使用,所以不能访问非静态成员。)</li>
<li>同理,类的任何对象不包含静态数据成员</li>
<li>静态成员不与对象,不与<code>this</code>指针发生交互,作为结果,静态成员函数不能声明为<code>const</code></li>
<li>可以通过类的对象调用静态成员函数,但此调用跟对象的状态并无关系,也就是说换个对象来调用是等价的,都等价于使用类名加域作用符来调用</li>
<li>静态成员一般定义在类的外部,因为每个对象都共享静态成员,避免多次定义</li>
<li>View static member as a normal function that has nothing to do with the class, except you must use <code>::</code> to access static members</li>
</ol></description></item><item><title>Linux 开机无声音</title><link>https://guyueshui.github.io/post/linux%E5%BC%80%E6%9C%BA%E6%97%A0%E5%A3%B0%E9%9F%B3/</link><pubDate>Sat, 26 Mar 2022 18:45:16 +0800</pubDate><guid>https://guyueshui.github.io/post/linux%E5%BC%80%E6%9C%BA%E6%97%A0%E5%A3%B0%E9%9F%B3/</guid><description><h2 id="开机后扬声器无声音">开机后扬声器无声音</h2>
<p>问题描述:个人笔记本电脑长久以来都有一个问题,开机之后扬声器没声音,从应用层看毫无问题,所有音乐视频照常播放,能调音量,就是没声音。必须插一下耳机,耳机里有声音。然后再拔出耳机,外部扬声器也有声音了。因此使用起来并无大碍,只需要准备一个耳机,开机之后插拔一下即可。</p></description></item><item><title>Linux 笔记本触摸板水平滚动问题</title><link>https://guyueshui.github.io/post/touchpad-horiz-scroll/</link><pubDate>Fri, 25 Mar 2022 23:03:59 +0800</pubDate><guid>https://guyueshui.github.io/post/touchpad-horiz-scroll/</guid><description><p>自打使用 linux 系统以来,触摸板这块的体验一只是个痛点:只支持基本的点击,双指垂直滚动。很久以来我就一直想要触摸板水平滚动的功能。今天终于实现了!</p>
<h2 id="synaptics">Synaptics</h2>
<p>其实很久以前就照抄过一份<code>xf86-input-synaptics</code>驱动程序的触摸板配置:</p></description></item><item><title>使用 Yield 实现 Python 协程</title><link>https://guyueshui.github.io/post/python-coroutine-with-yield/</link><pubDate>Sun, 20 Mar 2022 20:44:58 +0800</pubDate><guid>https://guyueshui.github.io/post/python-coroutine-with-yield/</guid><description><p>考虑如下代码:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="hl"><span class="lnt">23
</span></span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">async_call</span><span class="p">(</span><span class="n">it</span><span class="p">,</span> <span class="n">ret_list</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">value</span> <span class="o">=</span> <span class="n">ret_list</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">ret_list</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">ret_list</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="k">else</span> <span class="n">ret_list</span>
</span></span><span class="line"><span class="cl"> <span class="n">arg_list</span> <span class="o">=</span> <span class="n">it</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">arg_list</span><span class="p">)</span> <span class="ow">in</span> <span class="p">(</span><span class="nb">list</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="n">imp_func</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">arg_list</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nb">list</span><span class="p">(</span><span class="n">arg_list</span><span class="p">[</span><span class="mi">1</span><span class="p">:])</span>
</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">imp_func</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">arg_list</span><span class="p">,</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="n">callback</span> <span class="o">=</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">cb_args</span><span class="p">:</span> <span class="n">async_call</span><span class="p">(</span><span class="n">it</span><span class="p">,</span> <span class="n">cb_args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"> <span class="n">imp_func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="n">callback</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">make_async</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="k">def</span> <span class="nf">_wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="n">async_call</span><span class="p">(</span><span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">_wrapper</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fd</span><span class="p">(</span><span class="n">_idx</span><span class="p">,</span> <span class="n">callback</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;fd(</span><span class="si">%s</span><span class="s2">, </span><span class="si">%s</span><span class="s2">)&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">_idx</span><span class="p">,</span> <span class="n">callback</span><span class="p">))</span>
</span></span><span class="line hl"><span class="cl"> <span class="c1"># return &#39;EOF&#39;</span>
</span></span><span class="line"><span class="cl"> <span class="n">callback</span><span class="p">(</span><span class="s1">&#39;fd:</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">_idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@make_async</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fb</span><span class="p">(</span><span class="n">_idx</span><span class="p">,</span> <span class="n">callback</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;fb(</span><span class="si">%s</span><span class="s2">, </span><span class="si">%s</span><span class="s2">)&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">_idx</span><span class="p">,</span> <span class="n">callback</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">fd</span><span class="p">,</span> <span class="n">_idx</span>
</span></span><span class="line"><span class="cl"> <span class="n">callback</span><span class="p">(</span><span class="s1">&#39;fb:</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">ret</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fc</span><span class="p">(</span><span class="n">_idx</span><span class="p">,</span> <span class="n">callback</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;fc(</span><span class="si">%s</span><span class="s2">, </span><span class="si">%s</span><span class="s2">)&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">_idx</span><span class="p">,</span> <span class="n">callback</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="n">callback</span><span class="p">(</span><span class="s1">&#39;fc:</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">_idx</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nd">@make_async</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fa</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;fa(</span><span class="si">%s</span><span class="s2">, </span><span class="si">%s</span><span class="s2">)&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">))</span>
</span></span><span class="line"><span class="cl"> <span class="k">for</span> <span class="n">idx</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">):</span>
</span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="n">idx</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">fb</span>
</span></span><span class="line"><span class="cl"> <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">f</span> <span class="o">=</span> <span class="n">fc</span>
</span></span><span class="line"><span class="cl"> <span class="n">ret</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">f</span><span class="p">,</span> <span class="n">idx</span>
</span></span><span class="line"><span class="cl"> <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="si">%s</span><span class="s2">th iteration: ret in fa is </span><span class="si">%s</span><span class="s2">&#34;</span> <span class="o">%</span> <span class="p">(</span><span class="n">idx</span><span class="p">,</span> <span class="n">ret</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s1">&#39;__main__&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl"> <span class="n">fa</span><span class="p">()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>以上代码的运行结果为:</p></description></item><item><title>A point of python metaclass</title><link>https://guyueshui.github.io/post/python-metaclass/</link><pubDate>Sun, 12 Dec 2021 12:55:45 +0800</pubDate><guid>https://guyueshui.github.io/post/python-metaclass/</guid><description><h2 id="create-class-dynamically">Create <code>class</code> dynamically</h2>
<p>Python doc says:</p>
<blockquote>
<p>By default, classes are constructed using <code>type()</code>. The class body is executed in a new namespace and the class name is bound locally to the result of <code>type(name, bases, namespace)</code>.</p>
</blockquote>
<p>That&rsquo;s means, a <code>class</code> statement is equivalent to the call of <code>type</code> method with three arguments:</p>
<ul>
<li>name: name of the class</li>
<li>bases: tuple of the parent class (for inheritance, can be empty)</li>
<li>attrs: dictionary containing attributes names and values.</li>
</ul>
<p>For example, the following classes are identical:</p></description></item><item><title>V3Ray 的配置笔记</title><link>https://guyueshui.github.io/post/build-your-ladder/</link><pubDate>Tue, 07 Dec 2021 22:05:42 +0800</pubDate><guid>https://guyueshui.github.io/post/build-your-ladder/</guid><description><p>学生时代曾为整个课题组的师生搭建过一个梯子,稳定运行两年多,最近突然爬不上去了。
寻思是哪里出了问题,经过一番定位,原来是之前的免费域名到期了。遂于昨晚开启修补
之旅,无奈运气不太好,每一环节都出了问题,最终搞到凌晨 3 点才重新爬上了梯子。</p></description></item><item><title>Python Iterables</title><link>https://guyueshui.github.io/post/python-iterables/</link><pubDate>Sun, 21 Feb 2021 22:26:30 +0800</pubDate><guid>https://guyueshui.github.io/post/python-iterables/</guid><description><p>Python 的迭代器(iterator)、生成器(generator)、可迭代对象(iterable),虽是老生常谈,但我毕竟要记录一下自己的见解,因有此篇。</p></description></item><item><title>Linux 的休眠</title><link>https://guyueshui.github.io/post/linux-hibernate/</link><pubDate>Mon, 13 Jul 2020 22:44:33 +0800</pubDate><guid>https://guyueshui.github.io/post/linux-hibernate/</guid><description><p>先区分一下两个名词:睡眠(sleep)和休眠(hibernate)。</p>
<ul>
<li>睡眠:将工作镜像写入内存(RAM),以便快速恢复。内存读写很快,所以睡眠的特点就是“睡得快”和“醒得快”。对于笔记本来说,合上盖子就睡了,打开盖子你的工作区间即刻就能恢复,很是方便。但是睡眠有一个缺点,就是要给内存供电,一旦断电,你的镜像数据就会丢失,工作区间将不复存在。当然这来自于内存的固有特点,建议百度 RAM。</li>
<li>休眠:将工作镜像写入硬盘(disk,ROM),这样你也可以恢复工作区间。只是睡下去和醒过来的时间比内存慢不少。但是,它有一个好处就是断电了也不会丢失数据。当你再次开机,系统就会从硬盘里面读取镜像,恢复你的工作区间。</li>
</ul></description></item><item><title>一个 really simple 的 LaTeX 宏包</title><link>https://guyueshui.github.io/post/tex-sty-basic/</link><pubDate>Sun, 26 Apr 2020 09:25:09 +0800</pubDate><guid>https://guyueshui.github.io/post/tex-sty-basic/</guid><description><p>众所周知,LaTeX 是一个高效易用的排版软件,基本上只要找到合适的模板,剩下的就只剩码字了。比起 MS Word,简直不知道高到哪里去。就拿最近写论文的事来说,我先用 TeX 码好字,然后要投的那个刊需要用 Word 提交。转格式转了我一下午带一晚上,太痛苦了。深刻的体会到什么叫自以为是,MS Word 自作聪明地给你调格式。当你敲下回车之后,天知道它又会自动帮你做些什么?!</p></description></item><item><title>Latexmk 基础用法</title><link>https://guyueshui.github.io/post/latexmk-basic/</link><pubDate>Mon, 13 Apr 2020 23:50:55 +0800</pubDate><guid>https://guyueshui.github.io/post/latexmk-basic/</guid><description><p>怎么想到用 latexmk 的呢?写论文呗!</p>
<p>本来呢,我一直习惯于使用命令行手敲</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pdflatex someting.tex
</span></span></code></pre></td></tr></table>
</div>
</div><p>千万别小看这种重复劳动,它不仅帮你加深记忆,还有最完整的输出,让你一窥 Tex 排版系统的内裤(→_→,一本正经胡说八道中……)。还记得 Archlinux 的哲学名言吗?&ndash;Keep it simple and stupid (KISS)&ndash;说得太对了呀!</p></description></item><item><title>Gnome 应用启动缓慢</title><link>https://guyueshui.github.io/post/gnome-app-slow-start/</link><pubDate>Wed, 01 Apr 2020 23:01:36 +0800</pubDate><guid>https://guyueshui.github.io/post/gnome-app-slow-start/</guid><description><p>先看环境:</p>
<pre tabindex="0"><code>$ neofetch
-` yychi@MiBook-Air
.o+` ----------------
`ooo/ OS: Arch Linux x86_64
`+oooo: Host: TM1604 XMAKB3M0P0202
`+oooooo: Kernel: 5.5.13-arch2-1
-+oooooo+: Uptime: 5 mins
`/:-:++oooo+: Packages: 1153 (pacman)
`/++++/+++++++: Shell: zsh 5.8
`/++++++++++++++: Resolution: 1920x1080
`/+++ooooooooooooo/` WM: i3
./ooosssso++osssssso+` Theme: Adwaita [GTK2]
.oossssso-````/ossssss+` Icons: Adwaita [GTK2]
-osssssso. :ssssssso. Terminal: urxvt
:osssssss/ osssso+++. Terminal Font: DejaVu Sans Mono for Powerline
/ossssssss/ +ssssooo/- CPU: Intel i5-7200U (4) @ 3.100GHz
`/ossssso+/:- -:/+osssso+- GPU: NVIDIA GeForce MX150
`+sso+:-` `.-/+oso: GPU: Intel HD Graphics 620
`++:. `-/+/ Memory: 1608MiB / 7881MiB
.` `/
</code></pre><p>再看问题:Gnome 系软件(gedit, baobab, nautilus 等)启动龟速,通常需要等待 10-30s.</p></description></item><item><title>Metapost 学习笔记</title><link>https://guyueshui.github.io/post/metapost/</link><pubDate>Tue, 31 Mar 2020 09:20:44 +0800</pubDate><guid>https://guyueshui.github.io/post/metapost/</guid><description><p>想必你也有过这样的疑问,中学数学书上的那些精美的作图是如何画出来的?一直以来,我都想学习一门绘图语言,只是久久未能行动 orz&hellip;</p>
<p><img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3812944475,2492602811&amp;fm=26&amp;gp=0.jpg" alt=""></p>
<p>闲话少叙,开始学习!</p></description></item><item><title>声音的消亡</title><link>https://guyueshui.github.io/post/%E5%A3%B0%E9%9F%B3%E7%9A%84%E6%B6%88%E4%BA%A1/</link><pubDate>Wed, 25 Mar 2020 14:07:52 +0800</pubDate><guid>https://guyueshui.github.io/post/%E5%A3%B0%E9%9F%B3%E7%9A%84%E6%B6%88%E4%BA%A1/</guid><description><p>近日整理以前的文章,发现一个事实:我越来越不会说话,越来越不会表达,越来越没有自己的思想。</p>
<p>以前的我每隔几天都会发表空间说说,即使大部分属于“少年不识愁滋味,为赋新词强说愁”。但好歹能时常发表自己的观点、见解和感悟。我现在看起自己以前写过的东西,不论正确与否,起码可以通过写的文字窥见当时的自己,了解当时的想法,经过时空的转换,这些想法现在品起来十分有味道、并且非常有乐趣。</p></description></item><item><title>Bbb</title><link>https://guyueshui.github.io/slide/bbb/</link><pubDate>Mon, 23 Mar 2020 15:56:44 +0800</pubDate><guid>https://guyueshui.github.io/slide/bbb/</guid><description><h1 id="the-title">The Title</h1>
<p><big>Sub Title</big></p>
<p>Yychi | SIST</p>
<hr>
<h2 id="slide-2">Slide 2</h2>
<p>here comes $e=mc^2$.</p>
<p>$$
\mathbb{T} \mapsto A
$$</p></description></item><item><title>CCC</title><link>https://guyueshui.github.io/slide/ccc/</link><pubDate>Mon, 23 Mar 2020 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/slide/ccc/</guid><description><h1 id="hello-world">Hello world!</h1>
<p>This is my first slide.</p>
<hr>
<section data-shortcode-section>
<h1 id="hello-mars">Hello Mars!</h1>
<p>This is my second slide.</p>
<hr>
<h1 id="vertical-slide-1">Vertical slide 1</h1>
<p>This is verticle slide.</p>
<hr>
<h1 id="vertical-slide-2">Vertical slide 2</h1>
</section></description></item><item><title>Demo Slides</title><link>https://guyueshui.github.io/slide/aaa/</link><pubDate>Mon, 23 Mar 2020 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/slide/aaa/</guid><description><h1 id="hello-world">Hello world!</h1>
<p>This is my first <code>slide</code>.</p>
<p>$e=mc^2$</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kn">import</span><span class="w"> </span><span class="s">&#34;fmt&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="kd">func</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Hello world!&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">}</span></span></span></code></pre></td></tr></table>
</div>
</div>
<hr>
<section data-shortcode-section>
<h1 id="hello-mars">Hello Mars!</h1>
<p>This is my second slide.</p>
<hr>
<h1 id="vertical-slide-1">Vertical slide 1</h1>
<p>This is verticle slide.</p>
<hr>
<h1 id="vertical-slide-2">Vertical slide 2</h1>
</section></description></item><item><title>转义字符到底是什么</title><link>https://guyueshui.github.io/post/what-is-escape-character/</link><pubDate>Wed, 18 Mar 2020 22:41:06 +0800</pubDate><guid>https://guyueshui.github.io/post/what-is-escape-character/</guid><description><p>转义字符到底是啥?</p>
<p>实不相瞒我就是因为不知道才写下这篇文章,不,准确的说是这篇笔记 orz,既然是笔记,无所谓抄不抄了。每次说到转义字符,多少有点模糊,所以不如记下这篇笔记,以后忘了直接翻出来看看,复习起来要快一些。</p></description></item><item><title>小内存机器的自我救赎</title><link>https://guyueshui.github.io/post/nice-softwares/</link><pubDate>Thu, 12 Mar 2020 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/nice-softwares/</guid><description><p>在此记录一下我自己用过的非常棒的小软件。</p>
<p>有必要维护一个自己使用的软件列表。</p>
<p>套用一下 suckless 的 slogan,</p>
<blockquote>
<p>Everything sucks, we just suck less.</p>
<div style="text-align:right">-- suckless.org</div>
</blockquote>
<h2 id="下载">下载</h2>
<ul>
<li><a href="https://aria2.github.io">aria2c</a>: 命令行下载工具,支持下载种子、磁力等。有 RPC 模式,配合 WebUI 使用更佳。参考<a href="https://guyueshui.github.io/tricks/#aria2c">简介</a>。</li>
</ul>
<h2 id="多媒体">多媒体</h2>
<ul>
<li><a href="https://mpv.io">mpv</a>: 命令行多媒体播放器,拥有较强的扩展性和自定义的空间,另外我自己体验上来看比 mplayer 要流畅,mplayer 在我的机子上有丢帧,而 mpv 无明显丢帧。</li>
<li><a href="https://www.musicpd.org/">mpd/mpc</a>: 音乐播放,没有界面。mpd 作为服务端,mpc 作为客户端,占用内存非常低。</li>
<li><a href="https://obsproject.com/">OBS stuido</a>: 录屏软件,大而全,跨平台。虽然较大,但实践证明是兼容性最好的,在 linux 上也好使。可以正常录制扬声器和麦克风。</li>
<li><a href="https://github.com/MaartenBaert/ssr">SimpleScreenRecorder</a>: 录屏软件,配置比 obs 少但也够用。</li>
</ul>
<h2 id="文档">文档</h2>
<ul>
<li><a href="https://pwmt.org/projects/zathura/">zathura</a>: A vim-like pdf reader. vim 系快捷键,小而轻,但功能也相对较少。</li>
</ul>
<h2 id="截图">截图</h2>
<ul>
<li><a href="https://flameshot.org">flameshot</a>: gnome-screenshot 的替代品,支持截图后标记,复制到剪贴板;平台:Linux
<ul>
<li><code>flameshot gui</code>: 直接打开截屏功能,更多参考<code>flameshot -h</code>.</li>
</ul>
</li>
<li><a href="https://github.com/phw/peek">peek</a>: 小巧易用的录屏软件,支持录制 gif, mp4, webm 等格式。</li>
</ul>
<h2 id="看图">看图</h2>
<ul>
<li><a href="https://git.sr.ht/~exec64/imv">imv</a>: feh 的替代,支持多种格式(包括 gif<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>)。界面简洁只有一个图片框和 feh 一样,但是有必要的信息显示(overlay)。简洁党的最爱。</li>
<li><a href="https://github.com/AlienCowEatCake/ImageViewer">ImageViewer</a>: 纯 Qt 的图片查看器,简约不简陋。</li>
</ul>
<h2 id="效率">效率</h2>
<ul>
<li><a href="https://launchpad.net/xpad">xpad</a>: 小而轻的桌面便签。</li>
<li><a href="https://taskwarrior.org/">Taskwarrior</a>: A command-line todo manager,不要因为它的强大而忘记使用它的初衷。</li>
<li><a href="https://github.com/ranger/ranger">ranger</a>: File manager in terminal,三页分栏显示文件树,支持文件预览(需安装对应依赖),支持自定义命令,书签等。</li>
<li><a href="https://github.com/davatorium/rofi">rofi</a>: dmenu 替代品,窗口切换,应用启动器,简约大方,纯文本构成。</li>
<li><a href="https://www.voidtools.com/zh-cn/">Everything</a>: windows 平台,免费且简单易用的全局搜索器,该有的都有。</li>
<li><a href="http://qttabbar.wikidot.com/">QTTabBar</a>: 众所周知,windows 文件管理器十分难用,尤其是不支持 tab,所以,它来了。</li>
</ul>
<h2 id="学习">学习</h2>
<ul>
<li><a href="http://goldendict.org/">GoldenDict</a>: 离线词典,支持在线页面查词,接有道,维基等,可以看做是 Linux 上的 Eudic,支持多种离线字典格式,支持自定义快捷键查找剪贴板中的单词。</li>
</ul>
<h2 id="笔记">笔记</h2>
<ul>
<li><a href="https://obsidian.md/">Obsidian</a>: markdown 笔记软件,也可做个人知识库管理(过于方法论)。卖点有二,一是支持<a href="https://sspai.com/post/67996">双向链接</a>,并由此牵扯出一套方法论;二是你的数据你做主,一切笔记皆本地 markdown 文件。你拥有完全的掌控权,即便以后不用它,也很容易迁移到别的软件。对个人永久免费(付费版提供笔记同步、发布服务)。可玩性很强,太过知名,教程软文一搜一大把,还须记住记住本心为宜:我最初是为什么要用它来着?</li>
</ul>
<h2 id="锁屏">锁屏</h2>
<ul>
<li><a href="https://tools.suckless.org/slock/">slock</a>: suckless 出品,极简的锁屏软件。简单到什么程度呢?配置文件都没有,直接下源码改头文件来<a href="https://github.com/guyueshui/slock">配置</a>。</li>
</ul>
<h2 id="vscode-插件">VSCode 插件</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ code --list-extensions
</span></span><span class="line"><span class="cl">bungcip.better-toml
</span></span><span class="line"><span class="cl">tomoki1207.pdf
</span></span><span class="line"><span class="cl">huacnlee.autocorrect <span class="c1"># 修正中英混合排版的问题</span>
</span></span><span class="line"><span class="cl">huizhou.githd <span class="c1"># git history, blame on single file</span>
</span></span><span class="line"><span class="cl">mhutchie.git-graph <span class="c1"># git graph</span>
</span></span><span class="line"><span class="cl">KylinIDETeam.cmake-intellisence
</span></span><span class="line"><span class="cl">llvm-vs-code-extensions.vscode-clangd <span class="c1"># c++ dev</span>
</span></span><span class="line"><span class="cl">twxs.cmake <span class="c1"># cmake syntax support</span>
</span></span><span class="line"><span class="cl">vadimcn.vscode-lldb <span class="c1"># c++ debug</span>
</span></span><span class="line"><span class="cl">vscodevim.vim
</span></span></code></pre></td></tr></table>
</div>
</div><p>VSCode C++ 开发配置参考:</p></description></item><item><title>Brief Introduction to Shell Script</title><link>https://guyueshui.github.io/post/shell-intro/</link><pubDate>Fri, 22 Nov 2019 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/shell-intro/</guid><description><p>This article is mainly refered to &ldquo;The Linux Command Line&rdquo;<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. I just take
some most important things out of the book.</p>
<h2 id="expansion">Expansion</h2>
<p>Each time you type a command line and press the <kbd>Enter</kbd> key, bash
performs several processes upon the text before it carries out your command.
Just look an example:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">[</span>me@linuxbox ~<span class="o">]</span>$ <span class="nb">echo</span> *
</span></span><span class="line"><span class="cl">Desktop Documents ls-output.txt Music Pictures Public Templates Videos
</span></span></code></pre></td></tr></table>
</div>
</div><p>Why not display an asterisk? That&rsquo;s <strong>expansion</strong>! <code>*</code> <em>expands</em> to all files in
current directory.</p></description></item><item><title>Nueral Network Learning Notes</title><link>https://guyueshui.github.io/post/nn-notes/</link><pubDate>Tue, 29 Oct 2019 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/nn-notes/</guid><description><p>Hello here.</p>
<h2 id="cnn">CNN</h2>
<h3 id="conv-layer">Conv Layer</h3>
<p>Conv Layer is usually decreasing the input size, i.e., the output size may less or equal than input.</p>
<ul>
<li>take a volume as input: height x weight x depth, e.g., 32x32x3. Typically think an image having three channels: R, G, B.</li>
<li>a filter has the same depth as the input volume, e.g., 5x5x3 (since the filter always has a same depth as input vloume, the depth of the filter is sometimes omitted).</li>
<li>each filter convolving with the input will produce an activation map, two filters will produce two, etc.</li>
</ul>
<p>The result of the convolution at each location is just a scalar number (the result of taking a dot product between the filter and a small chunk of the image, i.e., $5\times 5 \times 3 = 75$-dimensional dot product + bias: $w^\top x + b$), which totally yields a 2D matrix (called <strong>activation map</strong>) as the filter sliding over the image. For example, 32x32x3 image convolved by 5x5x3 filter will yield a 28x28 activation map.</p></description></item><item><title>服务端开发预备知识</title><link>https://guyueshui.github.io/post/server-develop-preliminaries/</link><pubDate>Fri, 06 Sep 2019 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/server-develop-preliminaries/</guid><description><h2 id="操作系统">操作系统</h2>
<blockquote>
<p>摘自《程序员面试白皮书》</p>
</blockquote>
<h3 id="进程-vs线程">进程 vs.线程</h3>
<p>进程(process)与线程(thread)最大的区别是进程拥有自己的地址空间,某进程内的线程对于其他的进程不可见,即进程 A 不能通过传地址的方式直接读写进程 B 的存储区域。进程之间的通信需要通过进程间通信(Inter-process communication, IPC)。与之相对的,同一进程的各线程间可以直接通过传递地址或全局变量的方式传递信息。</p></description></item><item><title>设计模式学习笔记</title><link>https://guyueshui.github.io/post/design-pattern-notes/</link><pubDate>Mon, 02 Sep 2019 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/design-pattern-notes/</guid><description><p>如无特殊声明:本文所有 UML 图均出自《图说设计模式》。在此特别鸣谢!</p>
<h2 id="singleton">Singleton</h2>
<p>单例模式解决了全局变量的问题,全局只能创建一个实例,保证任何请求该实例的调用均返回同一个对象,保证不会被意外析构。</p></description></item><item><title>多线程学习笔记</title><link>https://guyueshui.github.io/post/concurrent-programming/</link><pubDate>Thu, 29 Aug 2019 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/concurrent-programming/</guid><description><p>开一篇多线程学习笔记,记录下在实习过程中遇到的一些简单问题。</p>
<blockquote>
<p>注意:这是一篇以学习笔记,难免有误,主要写给自己参考。请酌情判别,如有错误,也欢迎指正!</p></description></item><item><title>C++ 学习笔记</title><link>https://guyueshui.github.io/post/cpp-learn/</link><pubDate>Wed, 28 Aug 2019 00:00:00 +0000</pubDate><guid>https://guyueshui.github.io/post/cpp-learn/</guid><description><p>诚如是,Life is too short to learn c++. 此篇记录一些我在学习 cpp 过程中遇到的一些知识点,仅作记录并梳理之效。里面可能会有大量参考其他网络博客,如有侵权,请联系我删除之。</p>
<h2 id="reactor-vs-proactor">Reactor v.s. Proactor</h2>
<ul>
<li>epll/wait: reactor 模式,不停轮询,发现有事做,就做!</li>
<li>asio: proactor 模式,先注册好事件,如果事情发生了,通过回调函数处理。</li>
</ul>
<h2 id="几个常用的宏">几个常用的宏</h2>
<ul>
<li><code>__func__</code>: name of an function, exists in C99/C++11 (<code>__FUNCTION__</code> is non standard)</li>
<li><code>__LINE__</code>: line number of the code</li>
<li><code>__FILE__</code>: filename of the file</li>
<li><code>__DATE__</code> and <code>__TIME__</code>: as you wish</li>
</ul>
<h2 id="不要在-ctor-里调用虚函数">不要在 ctor 里调用虚函数</h2>
<p>总结来说:基类部分在派生类部分之前被构造,当基类构造函数执行时派生类中的数据成员还没被初始化。如果基类构造函数中的虚函数调用被解析成调用派生类的虚函数,而派生类的虚函数中又访问到未初始化的派生类数据,将导致程序出现一些未定义行为和 bug。</p>
<p>ctor 应该设计的尽量简单,确保对象可以被正确构造。在 ctor 中调用本类的非静态成员都是不安全的,因为他们还没被构造,而有些成员是依赖对象的,而此时对象还没有被成功构造。</p>
<h2 id="ctor-不能是虚函数">ctor 不能是虚函数</h2>
<ol>
<li>
<p>从存储空间角度:虚函数对应一个 vtable(虚函数表),这大家都知道,可是这个 vtable 其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable 来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到 vtable,所以构造函数不能是虚函数。</p>
</li>
<li>
<p>从使用角度:虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。
虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。</p>
</li>
<li>
<p>构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问它。但析构却不一定,我们往往通过基类的指针来销毁对象。这时候如果析构函数不是虚函数,就不能正确识别对象类型从而不能正确调用析构函数。</p>
</li>
</ol>
<p>——————————————————
版权声明:本文为 CSDN 博主「cainiao000001」的原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cainiao000001/article/details/81603782</p>
<h2 id="虚函数的工作原理">虚函数的工作原理</h2>
<p><a href="https://zhuanlan.zhihu.com/p/60543586">https://zhuanlan.zhihu.com/p/60543586</a></p>
<p>C++ 规定了虚函数的行为,但将实现方法留给了编译器的作者。不需要知道实现方法也可以很好的使用虚函数,但了解虚函数的工作原理有助于更好地理解概念。</p>
<p>通常,编译器处理虚函数的方法是:给每个对象添加一个隐藏成员。隐藏成员中保存了一个指向函数地址数组的指针。</p>
<p>这种数组称为虚函数表(Virtual Function Table, vtbl)。</p>
<p>虚函数表是一个数组,数组的元素是指针,指针指的是虚函数的地址。</p>
<p>具有虚函数的类的实例,都会在头部存一个指向虚函数表的指针。</p>
<h2 id="常见类型所占空间大小">常见类型所占空间大小</h2>
<table>
<thead>
<tr>
<th>TYPE</th>
<th style="text-align: right">Bytes</th>
</tr>
</thead>
<tbody>
<tr>
<td>(unsigned) int</td>
<td style="text-align: right">4</td>
</tr>
<tr>
<td>(unsigned) short</td>
<td style="text-align: right">2</td>
</tr>
<tr>
<td>(unsigned) long</td>
<td style="text-align: right">8</td>
</tr>
<tr>
<td>float</td>
<td style="text-align: right">4</td>
</tr>
<tr>
<td>double</td>
<td style="text-align: right">8</td>
</tr>
<tr>
<td>long double</td>
<td style="text-align: right">16</td>
</tr>
<tr>
<td>(unsigned) char</td>
<td style="text-align: right">1</td>
</tr>
<tr>
<td>bool</td>
<td style="text-align: right">1</td>
</tr>
</tbody>
</table>
<p>指针占几个字节 指针即为地址,指针几个字节跟语言无关,而是跟系统的寻址能力有关,譬如以前是 16 为地址,指针即为 2 个字节,现在一般是 32 位系统,所以是 4 个字节,以后 64 位,则就为 8 个字节。</p>
<blockquote>
<p>NOTE: 类成员函数指针一般为普通指针的两倍大小。</p>
</blockquote>
<p>literal <code>5.0</code>类型为<code>double</code>,<code>5.0f</code>类型为<code>float</code>。不加<code>f</code>后缀默认<code>double</code>.</p>
<h2 id="静态成员的初始化">静态成员的初始化</h2>
<p>当一个类包含静态成员时,最好的做法是在类中声明,在类外初始化。由于静态成员是所有对象共享的,如果在类内初始化,则每个对象构造时,都要执行一遍静态成员的初始化,这无疑是一种浪费。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">A</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="nf">fun</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> <span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="n">A</span><span class="o">::</span><span class="n">a</span> <span class="o">=</span> <span class="mi">233</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">B</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="kt">void</span> <span class="n">fun</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> <span class="p">...</span>
</span></span><span class="line"><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="cl"> <span class="k">static</span> <span class="n">string</span> <span class="n">str_</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">bool</span> <span class="n">done_</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">string</span> <span class="n">B</span><span class="o">::</span><span class="n">str_</span> <span class="o">=</span> <span class="s">&#34;hello, i am static&#34;</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="析构函数的调用时机">析构函数的调用时机</h2>
<p>The destructor is called whenever an object&rsquo;s lifetime ends, which includes</p>
<ul>
<li>program termination, for objects with static storage duration</li>
<li>thread exit, for objects with thread-local storage duration</li>
<li>end of scope, for objects with automatic storage duration and for temporaries whose life was extended by binding to reference</li>
<li>delete-expressin, for objects with dynamic storage duration</li>
<li>end of the full expression, for nameless temporaries</li>
<li>stack unwinding (栈回溯), for objects with automatic storage duration when an exception escapes their block, uncaught.</li>
</ul>
<p>cf. <a href="https://en.cppreference.com/w/cpp/language/destructor">https://en.cppreference.com/w/cpp/language/destructor</a></p>
<h2 id="常量">常量</h2>
<h3 id="literal-constants">Literal constants</h3>
<p>字面值常量
Cf. <a href="https://www.learncpp.com/cpp-tutorial/literals/">https://www.learncpp.com/cpp-tutorial/literals/</a></p>
<h3 id="symbolic-constants">Symbolic constants</h3>
<p>符号常量
Cf. <a href="https://www.learncpp.com/cpp-tutorial/const-constexpr-and-symbolic-constants/">https://www.learncpp.com/cpp-tutorial/const-constexpr-and-symbolic-constants/</a></p>
<ol>
<li>Const variables must be initialized</li>
<li>Function parameters for arguments passed by value should not be made const.</li>
<li>Don’t use const with return by value.</li>
</ol>
<p><strong>Runtime vs compile-time constants</strong></p>
<p>Runtime constants are constants whose initialization values can only be resolved at runtime (when your program is running). The following are examples of runtime constants:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">printInt</span><span class="p">(</span><span class="k">const</span> <span class="kt">int</span> <span class="n">x</span><span class="p">)</span> <span class="c1">// x is a runtime constant because the value isn&#39;t known until the program is run
</span></span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">x</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Enter your age: &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">age</span><span class="p">{};</span>
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cin</span> <span class="o">&gt;&gt;</span> <span class="n">age</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">const</span> <span class="kt">int</span> <span class="n">usersAge</span> <span class="p">{</span> <span class="n">age</span> <span class="p">};</span> <span class="c1">// usersAge is a runtime constant because the value isn&#39;t known until the program is run
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Your age is: &#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> <span class="n">printInt</span><span class="p">(</span><span class="n">age</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Compile-time constants are constants whose initialization values can be determined at compile-time (when your program is compiling). The following are examples of compile-time constants:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">double</span> <span class="n">gravity</span> <span class="p">{</span> <span class="mf">9.8</span> <span class="p">};</span> <span class="c1">// the compiler knows at compile-time that gravity will have value 9.8
</span></span></span><span class="line"><span class="cl"><span class="k">const</span> <span class="kt">int</span> <span class="n">something</span> <span class="p">{</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span> <span class="p">};</span> <span class="c1">// the compiler can resolve this at compiler time
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>Compile-time constants enable the compiler to perform optimizations that aren’t available with runtime constants. For example, whenever gravity is used, the compiler can simply substitute the identifier gravity with the literal double 9.8.</p>
<p>To help provide more specificity, C++11 introduced the keyword <code>constexpr</code>, which ensures that a constant must be a compile-time constant.</p>
<blockquote>
<p>Any variable that should not be modifiable after initialization and whose initializer is known at compile-time should be declared as <code>constexpr</code>.</p>
<p>Any variable that should not be modifiable after initialization and whose initializer is not known at compile-time should be declared as <code>const</code>.</p>
</blockquote>
<p>Note that literals are also implicitly constexpr, as the value of a literal is known at compile-time.</p>
<p>A <strong>constant expression</strong> is an expression that can be evaluated at compile-time. For example:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span><span class="p">;</span> <span class="c1">// 3 + 4 evaluated at compile-time
</span></span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>In the above program, because the literal values 3 and 4 are known at compile-time, the compiler can evaluate the expression 3 + 4 at compile-time and substitute in the resulting value 7. That makes the code faster because 3 + 4 no longer has to be calculated at runtime.</p>
<p>Constexpr variables can also be used in constant expressions:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="k">constexpr</span> <span class="kt">int</span> <span class="n">x</span> <span class="p">{</span> <span class="mi">3</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"> <span class="k">constexpr</span> <span class="kt">int</span> <span class="n">y</span> <span class="p">{</span> <span class="mi">4</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="p">;</span> <span class="c1">// x + y evaluated at compile-time
</span></span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>In the above example, because x and y are constexpr, the expression x + y is a constant expression that can be evaluated at compile-time. Similar to the literal case, the compiler can substitute in the value 7.</p>
<h3 id="object-like-preprocessor-macros-vs-symbolic-constants">Object-like preprocessor macros v.s. symbolic constants</h3>
<p>Object-like macro has the form:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#define identifier substitution_text
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>Whenever the preprocessor encounters this directive, any further occurrence of <em>identifier</em> is replaced by <em>substitution_text</em>. The identifier is traditionally typed in all capital letters, using underscores to represent spaces.</p>
<blockquote>
<p>Avoid using #define to create symbolic constants macros. Use const or constexpr variables instead.</p>
</blockquote>
<p>Macros can have naming conflicts with normal code. For example:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;someheader.h&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="n">beta</span> <span class="p">{</span> <span class="mi">5</span> <span class="p">};</span>
</span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">beta</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>If someheader.h happened to #define a macro named beta, this simple program would break, as the preprocessor would replace the int variable beta’s name with whatever the macro’s value was. This is normally avoided by using all caps for macro names, but it can still happen.</p>
<h3 id="using-symbolic-constants-throughout-a-multi-file-program">Using symbolic constants throughout a multi-file program</h3>
<p>Cf. <a href="https://www.learncpp.com/cpp-tutorial/sharing-global-constants-across-multiple-files-using-inline-variables/">https://www.learncpp.com/cpp-tutorial/sharing-global-constants-across-multiple-files-using-inline-variables/</a></p>
<h2 id="内存布局">内存布局</h2>
<h3 id="结构体">结构体</h3>
<p>C++ 规范在“结构”上使用了和 C 相同的,简单的内存布局原则:成员变量按其被声明的顺序排列,按具体实现所规定的对齐原则在内存地址上对齐。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">struct</span> <span class="nc">S</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="n">a</span><span class="p">;</span> <span class="c1">// memory location #1
</span></span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nl">b</span> <span class="p">:</span> <span class="mi">5</span><span class="p">;</span> <span class="c1">// memory location #2
</span></span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nl">c</span> <span class="p">:</span> <span class="mi">11</span><span class="p">,</span> <span class="c1">// memory location #2 (continued)
</span></span></span><span class="line"><span class="cl"> <span class="kt">char</span> <span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nl">d</span> <span class="p">:</span> <span class="mi">8</span><span class="p">;</span> <span class="c1">// memory location #3
</span></span></span><span class="line"><span class="cl"> <span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="kt">int</span> <span class="nl">ee</span> <span class="p">:</span> <span class="mi">8</span><span class="p">;</span> <span class="c1">// memory location #4
</span></span></span><span class="line"><span class="cl"> <span class="p">}</span> <span class="n">e</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span> <span class="n">obj</span><span class="p">;</span> <span class="c1">// The object &#39;obj&#39; consists of 4 separate memory locations
</span></span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>类的静态成员不占用类的空间,静态成员在程序数据段中。</li>
</ul>
<h3 id="对齐">对齐</h3>
<p>Cf. <a href="https://www.learncpp.com/cpp-tutorial/object-sizes-and-the-sizeof-operator/#comment-563585">https://www.learncpp.com/cpp-tutorial/object-sizes-and-the-sizeof-operator/#comment-563585</a></p>
<p>Cf. <a href="http://www.catb.org/esr/structure-packing/">http://www.catb.org/esr/structure-packing/</a></p>
<h2 id="模板">模板</h2>
<h3 id="重载与特化">重载与特化</h3>
<p>从编译到函数模板的调用,编译器必须在非模板重载、模板重载和模板重载的特化间决定。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;</span> <span class="k">class</span> <span class="nc">T</span> <span class="o">&gt;</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="p">);</span> <span class="c1">// #1:模板重载
</span></span></span><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;</span> <span class="k">class</span> <span class="nc">T</span> <span class="o">&gt;</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">);</span> <span class="c1">// #2:模板重载
</span></span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">f</span><span class="p">(</span><span class="kt">double</span><span class="p">);</span> <span class="c1">// #3:非模板重载
</span></span></span><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;&gt;</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span> <span class="c1">// #4: #1 的特化
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">f</span><span class="p">(</span><span class="sc">&#39;a&#39;</span><span class="p">);</span> <span class="c1">// 调用 #1
</span></span></span><span class="line"><span class="cl"><span class="n">f</span><span class="p">(</span><span class="k">new</span> <span class="kt">int</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span> <span class="c1">// 调用 #2
</span></span></span><span class="line"><span class="cl"><span class="n">f</span><span class="p">(</span><span class="mf">1.0</span><span class="p">);</span> <span class="c1">// 调用 #3
</span></span></span><span class="line"><span class="cl"><span class="n">f</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">// 调用 #4
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>注意只有非模板和初等模板重载参与重载决议。特化不是重载,且不受考虑。只有在重载决议选择最佳匹配初等函数模板后,才检验其特化以查看何为最佳匹配。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;</span> <span class="k">class</span> <span class="nc">T</span> <span class="o">&gt;</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="p">);</span> <span class="c1">// #1:所有类型的重载
</span></span></span><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;&gt;</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span><span class="p">);</span> <span class="c1">// #2:为指向 int 的指针特化 #1
</span></span></span><span class="line"><span class="cl"><span class="k">template</span><span class="o">&lt;</span> <span class="k">class</span> <span class="nc">T</span> <span class="o">&gt;</span> <span class="kt">void</span> <span class="n">f</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">);</span> <span class="c1">// #3:所有指针类型的重载
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">f</span><span class="p">(</span><span class="k">new</span> <span class="kt">int</span><span class="p">(</span><span class="mi">1</span><span class="p">));</span> <span class="c1">// 调用 #3,即使通过 #1 的特化会是完美匹配
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>即重载的优先级要高于特化。</p>
<p>关于模板函数重载的更多内容,参考 <a href="https://en.cppreference.com/w/cpp/language/function_template">function_template</a>。</p>
<h2 id="预编译">预编译</h2>
<p>Cf. <a href="https://www.learncpp.com/cpp-tutorial/introduction-to-the-preprocessor/">https://www.learncpp.com/cpp-tutorial/introduction-to-the-preprocessor/</a></p>
<h3 id="include"><code>#include</code></h3>
<p>When you #include a file, the preprocessor replaces the #include directive with the contents of the included file. The included contents are then preprocessed (along with the rest of the file), and then compiled.</p>
<h3 id="macro-defines">Macro defines</h3>
<p>The #define directive can be used to create a macro. In C++, a macro is a rule that defines how input text is converted into replacement output text.</p>
<p>There are two basic types of macros: <em>object-like macros</em>, and <em>function-like macros</em>.
Object-like macros can be defined in one of two ways:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#define identifier
</span></span></span><span class="line"><span class="cl"><span class="cp">#define identifier substitution_text
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="object-like-macros-dont-affect-other-preprocessor-directives">Object-like macros don’t affect other preprocessor directives</h3>
<p>结论:宏展开在预编译指令 (Preprocessor directives) 无效。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#define PRINT_JOE
</span></span></span><span class="line"><span class="cl"><span class="cp">#ifdef PRINT_JOE </span><span class="c1">// 此处会否将&#39;PRINT_JOE&#39;替换为空呢?
</span></span></span><span class="line"><span class="cl"><span class="c1">// ...
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>Macros only cause text substitution for normal code. Other preprocessor commands are ignored. Consequently, the PRINT_JOE in #ifdef PRINT_JOE is left alone.</p>
<p>For example:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#define FOO 9 </span><span class="c1">// Here&#39;s a macro substitution
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef FOO </span><span class="c1">// This FOO does not get replaced because it’s part of another preprocessor directive
</span></span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">FOO</span><span class="p">;</span> <span class="c1">// This FOO gets replaced with 9 because it&#39;s part of the normal code
</span></span></span><span class="line"><span class="cl"><span class="cp">#endif
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>In actuality, the output of the preprocessor contains no directives at all &ndash; they are all resolved/stripped out before compilation, because the compiler wouldn’t know what to do with them.</p>
<h3 id="the-scope-of-defines">The scope of defines</h3>
<p>Once the preprocessor has finished, all defined identifiers from that file are discarded. <strong>This means that directives are only valid from the point of definition to the end of the file in which they are defined</strong>. Directives defined in one code file do not have impact on other code files in the same project.</p>
<p>宏定义仅在本文件有效,一旦预编译阶段结束,所有宏都将失效。因为,预编译就是将所有的预编译指令都处理掉,该替换的替换(宏展开),该选择的选择,该丢弃的丢弃(条件编译),然后交给编译器去编译,谨记:编译器是读不懂预编译指令的!</p>
<p>Consider the following example:</p>
<p>function.cpp:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">doSomething</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"><span class="cp">#ifdef PRINT
</span></span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Printing!&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif
</span></span></span><span class="line"><span class="cl"><span class="cp">#ifndef PRINT
</span></span></span><span class="line"><span class="cl"> <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&#34;Not printing!&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="cp">#endif
</span></span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>main.cpp:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">void</span> <span class="nf">doSomething</span><span class="p">();</span> <span class="c1">// forward declaration for function doSomething()
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="cp">#define PRINT
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="n">doSomething</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>The above program will print:</p>
<pre tabindex="0"><code>Not printing!
</code></pre><p>Even though PRINT was defined in main.cpp, that doesn’t have any impact on any of the code in function.cpp (PRINT is only #defined from the point of definition to the end of main.cpp). This will be of consequence when we discuss header guards in a future lesson.</p>
<h2 id="header-files">Header files</h2>
<p>Cf. <a href="https://www.learncpp.com/cpp-tutorial/header-files/">https://www.learncpp.com/cpp-tutorial/header-files/</a></p>
<p>对于多文件项目,文件是单独编译的。要想调用一个自定义函数,linker 必须能找到这个函数在哪里定义。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="p">);</span> <span class="c1">// forward declaration
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="c1">// add(3, 5);
</span></span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>上述文件是可以编译通过的,因为没有发生对<code>add</code>的调用,所以 linker 不会去找<code>add</code>的定义(当然如果要找也找不到)。</p>
<p>但是如果某处发起了对<code>add</code>的调用(例如去掉注释),那么上述程序在 link 阶段会报错:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl">yychi@~&gt; clang test_linker.cpp
</span></span><span class="line"><span class="cl">/usr/bin/ld: /tmp/test_linker-e1bb8b.o: in <span class="k">function</span> <span class="sb">`</span>main<span class="s1">&#39;:
</span></span></span><span class="line"><span class="cl"><span class="s1">test_linker.cpp:(.text+0x1a): undefined reference to `add(int, int)&#39;</span>
</span></span><span class="line"><span class="cl">clang-13: error: linker <span class="nb">command</span> failed with <span class="nb">exit</span> code <span class="m">1</span> <span class="o">(</span>use -v to see invocation<span class="o">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>在多文件编程时,往往需要 forawrd declaration,这些前置声明必须在其他某个地方被定义且只被定义一次。这样,linker 才能正确的完成链接。任何重复定义或未定义都会在 link 阶段报错。</p>
<p>考虑如下例子:</p>
<p>add.cpp:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="cl"><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span>