-
Notifications
You must be signed in to change notification settings - Fork 3
/
02.ass
852 lines (850 loc) · 124 KB
/
02.ass
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
[Script Info]
Title: RAII 与智能指针
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
Original Script: woclass
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,微软雅黑,80,&H00FFFFFF,&H0000FFFF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2.0,1,2,10,10,10,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:01.79,0:00:04.79,Default,,0,0,0,,好,我们现在开始上课
Dialogue: 0,0:00:04.79,0:00:08.45,Default,,0,0,0,,首先这是我们的第二节课
Dialogue: 0,0:00:08.45,0:00:28.79,Default,,0,0,0,,然后第一节已经讲过了,录播是上传到这里,然后就是这一期主要是本来打算讲ST1容器的,但后来发现内容太多了,就只讲了III和内存管理
Dialogue: 0,0:00:28.79,0:00:48.46,Default,,0,0,0,,首先我们来看一个例子,就是我们先用拍送的一个案例,就是我已知一个列表,我想求出列表里所有数的和那如果要用 C++ 的话,是怎么做呢?
Dialogue: 0,0:00:48.46,0:00:56.96,Default,,0,0,0,,首先就是从C语言讲,C语言的话呢要定义一个数组
Dialogue: 0,0:00:56.96,0:01:11.70,Default,,0,0,0,,首先用my lock 分配一块内存,然后因为是四个数组成的数组,所以分配4层inter的大小,各内存的比特才能存储
Dialogue: 0,0:01:11.70,0:01:33.25,Default,,0,0,0,,然后返回的是一个指针,指针通过括号零代表从指针开始第零个数,然后第一个数,第二个数、第三个数这样嗯然后之后呢就是用for 循环从零加到NV也就是它的速度长度
Dialogue: 0,0:01:33.25,0:01:40.74,Default,,0,0,0,,然后每一个都累加到项目里,然后最后再打印输出就得到了结果
Dialogue: 0,0:01:40.74,0:01:47.58,Default,,0,0,0,,当然最后还要把分配的给释放一下,有什么问题吗?
Dialogue: 0,0:01:48.38,0:01:53.06,Default,,0,0,0,,有问题吗?
Dialogue: 0,0:01:53.06,0:01:54.77,Default,,0,0,0,,没问题,继续了
Dialogue: 0,0:01:54.77,0:02:01.05,Default,,0,0,0,,然后我们 C++ 进入 C++ 时代以后,有什么不同呢?
Dialogue: 0,0:02:01.05,0:02:18.18,Default,,0,0,0,,可以看一下我们 C++ 引入了容器库,就是本来我们是需要定义一个长度,然后再分配一块内存返回一个指针,现在直接把它们分装成了一个类
Dialogue: 0,0:02:18.18,0:02:27.03,Default,,0,0,0,,然后这个类还是基于模板的,就是我这里可以是int 整形,也可以是float 浮点型
Dialogue: 0,0:02:27.03,0:02:39.60,Default,,0,0,0,,然后这里传入数据也是像原来一样,通过这个方括号,然后求长度的时候,求那个长度的时候可以用V点size
Dialogue: 0,0:02:39.60,0:02:50.19,Default,,0,0,0,,这个size 就是我们原来指定的4 ,然后上面呢也是一个个一般从零加到它的size ,这size 和是一样
Dialogue: 0,0:02:50.19,0:03:14.09,Default,,0,0,0,,然后我们输出呢也不用print f 了,因为这里百分比D就代表比如我想要输出的是int 类型,我得换成百分比D我想要输出浮点得换成F那如果我不小心搞错呢,比如上面是float 的,我却用了百分比低,那打出来就不对了
Dialogue: 0,0:03:14.09,0:03:28.62,Default,,0,0,0,,但是 C++ 它有运算符重载,就是这个上面它会根据实际是什么类型去调用不同的那个输出函数,有什么问题吗?
Dialogue: 0,0:03:28.62,0:03:32.53,Default,,0,0,0,,因为有的同学要考四级吗?
Dialogue: 0,0:03:33.50,0:03:48.81,Default,,0,0,0,,然后就是这个是运算符存在,嗯,它可以实现一种多态的效果,然后就是 C++ 984第1个标准化的 C++
Dialogue: 0,0:03:48.81,0:03:54.85,Default,,0,0,0,,然后之后呢过了一段时间又提出 C++ 11标准
Dialogue: 0,0:03:54.85,0:04:07.50,Default,,0,0,0,,这个酒吧呢指的是1998年,然后一一呢指的是2011年,就是它是在11年左右推出的一个新标准
Dialogue: 0,0:04:07.50,0:04:10.08,Default,,0,0,0,,它有一个什么进步呢?
Dialogue: 0,0:04:10.08,0:04:16.41,Default,,0,0,0,,就是之前是先要分配一个victor ,然后一个个复制进去
Dialogue: 0,0:04:16.94,0:04:24.30,Default,,0,0,0,,那在这个新标准里呢,它支持这个圆括这个叫花括号表达
Dialogue: 0,0:04:24.63,0:04:40.70,Default,,0,0,0,,就是在夸括号里通过逗号隔开,然后就可以输入一个像列表一样的东西,让他去初始化这个V这样的话呢他就写起来方便了
Dialogue: 0,0:04:41.66,0:05:04.52,Default,,0,0,0,,然后呢,就是求值呢,当然还是像原来那么求嗯,然后其实是1加加11 ,还引入了一个很方便的,就是它可以使用基于范围的for 循环这个和python 的for in 就很像了,它是怎么变的?
Dialogue: 0,0:05:04.52,0:05:13.18,Default,,0,0,0,,就是一开始是要指定一个下标从零到它的大小,现在就只需要for VI
Dialogue: 0,0:05:13.18,0:05:29.89,Default,,0,0,0,,然后V也就是把V里面每个元素变成VI,然后VI把它累加到上午上,这样的话就能少写一个那个size 杠T然后这些这些这些操作了
Dialogue: 0,0:05:29.89,0:05:44.72,Default,,0,0,0,,而且它是基于迭代器呢,就是它对于类似的这种没有下标的,它也能正常使用,更加方便,有问题吗?
Dialogue: 0,0:05:45.17,0:05:49.74,Default,,0,0,0,,就是然后那没问题,我继续啦
Dialogue: 0,0:05:51.06,0:05:53.73,Default,,0,0,0,,能看得见吗?
Dialogue: 0,0:05:56.41,0:05:58.66,Default,,0,0,0,,那我继续了
Dialogue: 0,0:05:58.66,0:06:16.67,Default,,0,0,0,,然后然后就是我们 C++ 还有一些算法模板,就比如说一起它的功能就是把V的起始到终点,就在每个数都调用一遍这个分开
Dialogue: 0,0:06:16.67,0:06:31.75,Default,,0,0,0,,然后分开的参数是硬卡,也就是说要把phone 里面每一次都调用这个V的每一个下标,每一个值就是这个四这个三这个V的每一
Dialogue: 0,0:06:31.75,0:06:36.43,Default,,0,0,0,,然后呢,他现在是去累加了一个全局的资
Dialogue: 0,0:06:37.01,0:06:47.85,Default,,0,0,0,,也就是说funk 执行事变以后,它的结果就是这四个的和然后就是好像是20还是什么的
Dialogue: 0,0:06:47.85,0:07:08.02,Default,,0,0,0,,总之它就算出了这个和然后for each 呢它是一种模板函数,它就可以套用到任何一个支持begin 和end 的容器,包括list 或者map ,甚至是别的任何支持迭代器的容器都可以用
Dialogue: 0,0:07:08.02,0:07:13.98,Default,,0,0,0,,这个模板,没问题吧
Dialogue: 0,0:07:15.22,0:07:33.17,Default,,0,0,0,,然后就是现在就是刚才看到这个phone 卡,它必须为一个独立的外部的函数,但是这样就意味着必须要去声明一个全局的项目就很麻烦
Dialogue: 0,0:07:33.50,0:07:43.83,Default,,0,0,0,,然后对丫丫实际要引入亮度的表达式,这样的话就可以把分写在局部
Dialogue: 0,0:07:43.83,0:07:49.90,Default,,0,0,0,,然后这个和表示它会引诱外面的项目变量
Dialogue: 0,0:07:50.53,0:08:03.89,Default,,0,0,0,,这样我的上午就可以为一个局部变量,然后参数啊还是VI这样写起来,就和之前的这个form 是差不多,但它是基于模板
Dialogue: 0,0:08:06.05,0:08:12.18,Default,,0,0,0,,今天早了一点,因为今天内容比较多嘛
Dialogue: 0,0:08:15.06,0:08:25.81,Default,,0,0,0,,然后就是我们现在十一是2011年的标准,后来又引入了2014年的 C++ 14
Dialogue: 0,0:08:25.81,0:08:30.00,Default,,0,0,0,,他这时候开始可以用auto 作为参数
Dialogue: 0,0:08:30.00,0:08:38.66,Default,,0,0,0,,本来我们就是如果这个换成了float ,我还得把这个换成float ,这个也换成float
Dialogue: 0,0:08:38.66,0:08:45.24,Default,,0,0,0,,然后它这个的话它就支持参数是可以是任意类型的
Dialogue: 0,0:08:45.57,0:08:54.98,Default,,0,0,0,,这样的话如果我这里换成float ,我这个模板都不需要改,这样的话呢就更加的通用了
Dialogue: 0,0:08:56.57,0:09:09.38,Default,,0,0,0,,然后哎我看一下那个有没有生成,然后就是到了2017年发布的 C++ 17标准
Dialogue: 0,0:09:09.38,0:09:20.26,Default,,0,0,0,,这个标准现在需要在symbolist 里增加这么一行才能使用了,就代表 C++ 标准是17
Dialogue: 0,0:09:20.26,0:09:23.68,Default,,0,0,0,,然后它有一个什么进步呢?
Dialogue: 0,0:09:23.68,0:09:28.03,Default,,0,0,0,,就是这个backed call it 可以省略掉了
Dialogue: 0,0:09:28.03,0:09:49.02,Default,,0,0,0,,因为他看到右边这四个数都是整,然后左边这里就不需要再指定一遍映衬了,他就直接微课堂括号里不需要那个加括号,他就这个叫编译器参数推断,简称CTAD
Dialogue: 0,0:09:49.02,0:10:02.97,Default,,0,0,0,,然后很多比如top o 啊,还有片啊,这种也做了CTAD就不再需要making 片那个帮手函数嗯有问题吗?
Dialogue: 0,0:10:05.10,0:10:18.01,Default,,0,0,0,,然后 C++ 17就是他还引入了一些算法,这个都是定义在numeric 这个头文件这里面包括reduce reduce
Dialogue: 0,0:10:18.01,0:10:35.03,Default,,0,0,0,,我们经常说它其实就是相当于把这每一个的数据求和,就不再需要我们自己写一个上午,然后循环去加了,它就自动给你作为返回
Dialogue: 0,0:10:35.64,0:10:47.66,Default,,0,0,0,,然后或者如果你不想要加,或者是乘的话,就可以用下面这个复杂的形式,这里换成一这里换成STD探路子
Dialogue: 0,0:10:47.66,0:10:55.94,Default,,0,0,0,,也就是从一开始,然后一个个相乘,默认情况下是零和加,也就是默认是加法
Dialogue: 0,0:10:55.94,0:11:15.75,Default,,0,0,0,,如果你这里换成一,这里换成乘,这就是乘,等于这就是一它就是一个连乘,而不是连加嗯 C++ 11 ,你看的是什么时候的书,就是这些书其实是非常老的
Dialogue: 0,0:11:15.75,0:11:28.68,Default,,0,0,0,,我推荐你去看一下这个就是这个网站嗯,就是这个网站
Dialogue: 0,0:11:28.68,0:11:58.96,Default,,0,0,0,,然后它有一个有一个表,就是嗯哎呀总之总之就是你可以搜一下,compile support , 就是他现在已经更新到 C++ 二三了,但是虽然已经发布的只有20 ,但是二三已经是在施工中了
Dialogue: 0,0:11:58.96,0:12:04.25,Default,,0,0,0,,然后他们很多的这个特性也都列在这个表上
Dialogue: 0,0:12:04.88,0:12:36.79,Default,,0,0,0,,可以呀,就是你可以用这个嗯唉我的表呢就是你可以用这样一个表达式,也是我们的这个lambda 表达式return x 加Y,这样就实现自定义
Dialogue: 0,0:12:37.18,0:12:45.89,Default,,0,0,0,,就是他这个可以是任意一个函数,然后我们用level 表达式把它换成乘法
Dialogue: 0,0:12:45.89,0:13:04.39,Default,,0,0,0,,然后这里换成一它就是一个内存操作啊,可以看啊,这就是24 ,因为4乘3乘2乘1就是24
Dialogue: 0,0:13:04.39,0:13:18.30,Default,,0,0,0,,然后我们这里换成加呢,然后这是初始值,这个是这个是那个二元运算,这样就变成了他们的和是十,知道了吧?
Dialogue: 0,0:13:21.39,0:13:29.23,Default,,0,0,0,,然后你可以看到这是当前所有的编译器都支持哪些那个功能
Dialogue: 0,0:13:29.23,0:13:35.63,Default,,0,0,0,,就是目前来看 C++ 二三已经有很多人开始支持了
Dialogue: 0,0:13:35.63,0:13:41.15,Default,,0,0,0,,然后20已经就是微软是第一个全部支持的
Dialogue: 0,0:13:41.15,0:13:53.67,Default,,0,0,0,,然后还有很多就是现在现在行业主流用的是10 ,但是 C++ 20的话已经被微软的编译器几乎全部支持了
Dialogue: 0,0:13:54.00,0:14:09.04,Default,,0,0,0,,然后就是唉我的PPT呢,然后就是我们现在进入到未来就是时期已经是当前标准的那个版本
Dialogue: 0,0:14:09.04,0:14:38.41,Default,,0,0,0,,然后20它现在引入了区间,这其实跟python 的这个map 很像,就transform 相当于python 的map ,然后filter 也是python 的filter ,它可以过滤出所有大于等于0的函数啊,0X然后大于等于零的数呢再被去做一个变换,也就是把它们求一下根号,然后求出来
Dialogue: 0,0:14:38.41,0:14:45.53,Default,,0,0,0,,这样的话呢就只有大于零的数会被求根号,防止它出现错
Dialogue: 0,0:14:46.12,0:14:56.20,Default,,0,0,0,,然后这个pam 表达式呢也非常的方便,它就代表先把V送到这里处理一下,再送到这里处理一下
Dialogue: 0,0:14:56.20,0:15:02.41,Default,,0,0,0,,你们可以去看一下这个链接,了解更多这方面的这个用法
Dialogue: 0,0:15:02.41,0:15:10.95,Default,,0,0,0,,但是现在20还没有普遍落地,以及这个其实是有一个库叫ranges 微商可以替代
Dialogue: 0,0:15:12.89,0:15:16.52,Default,,0,0,0,,然后他们又做了一件什么事呢?
Dialogue: 0,0:15:16.52,0:15:28.82,Default,,0,0,0,,就是他现在不再需要include 这种暴力替换的手段,他们真正的实现了模块,把模块作为一个语言的基本概念
Dialogue: 0,0:15:28.82,0:15:37.55,Default,,0,0,0,,然后就可以通过import 来导入他们的这些本来是头文件,现在叫模块了
Dialogue: 0,0:15:38.67,0:15:56.27,Default,,0,0,0,,然后现在他这个函数参数也可以是auto 了,这个和之前template 7 ,然后这里七和和是一样的,就他这样写起来无非是方便一些,其实是一样的
Dialogue: 0,0:15:56.27,0:16:19.83,Default,,0,0,0,,然后 C++ 20还引入了携程这个携程这个call 一样的,就是他们当中一个生成器的特嗯,然后这个其实我也没有自己试验过,因为GCC还不是非常支持携程,然后样子和派送你的样子其实很像
Dialogue: 0,0:16:19.83,0:16:29.73,Default,,0,0,0,,就是他返这里返回,就相当于直接把这个代码嵌入到这里一样,但编写起来就更加方便
Dialogue: 0,0:16:29.73,0:16:36.69,Default,,0,0,0,,然后他们还引入了format ,这是很多人都在追求的
Dialogue: 0,0:16:36.69,0:16:52.82,Default,,0,0,0,,以前都是通过fmp 这个库,现在可以用标准库里的format to see out , 然后它的格式化和python 一样,使用这个大括号表示VI显示到这里
Dialogue: 0,0:16:53.34,0:17:03.01,Default,,0,0,0,,对对对,都要有了,新加一下,一直在向python 和rest 学习
Dialogue: 0,0:17:03.50,0:17:07.52,Default,,0,0,0,,然后我们跑的是不是有点远了?
Dialogue: 0,0:17:07.52,0:17:17.11,Default,,0,0,0,,就是虽然 C++ 20看起来很香,但这个import 目前甚至连c mac 都没有支持
Dialogue: 0,0:17:17.11,0:17:22.68,Default,,0,0,0,,好像据说x mac 已经支持了,但是我们不会用
Dialogue: 0,0:17:22.68,0:17:30.42,Default,,0,0,0,,所以我们目前的那个这个课呢,主要就是到 C++ 17为止
Dialogue: 0,0:17:30.42,0:17:37.54,Default,,0,0,0,,当然20它也引入了很多对多线程编程比较好的特性
Dialogue: 0,0:17:37.54,0:17:43.42,Default,,0,0,0,,比如这个future 什么携程啊,什么还有barrier 这种
Dialogue: 0,0:17:43.42,0:17:50.23,Default,,0,0,0,,但是我们可以通过使用英特尔的TBB那个很卡吗?
Dialogue: 0,0:17:51.55,0:17:54.25,Default,,0,0,0,,是我的问题吗?
Dialogue: 0,0:17:55.66,0:18:05.99,Default,,0,0,0,,就是这个本来是T比比你的东西,他现在进入标准库哦,是他的问题吗?
Dialogue: 0,0:18:07.08,0:18:17.63,Default,,0,0,0,,好吧,然后我们来看看就是刚才提到的一个一个求职的例子
Dialogue: 0,0:18:17.63,0:18:31.51,Default,,0,0,0,,这里面有哪些是好的思,首先这是C语言的班子,然后这是 C++ 980的版本,这主要有什么区别呢?
Dialogue: 0,0:18:32.23,0:18:43.89,Default,,0,0,0,,首先第一个区别就可以看到,这里是两个,先要指定它的大小,然后再要知道它分配一块内存
Dialogue: 0,0:18:44.23,0:18:54.72,Default,,0,0,0,,而在 C++ 里面它就分装成了一个对象的初始化,也就是这两个,因为它们逻辑上是相关的
Dialogue: 0,0:18:54.72,0:19:01.35,Default,,0,0,0,,NV一表示V一的大小,那么就干脆将它们包装成一个类
Dialogue: 0,0:19:01.35,0:19:11.30,Default,,0,0,0,,就比如要表达数组的话,就需要知道V和NV然后V呢就变成了这个通过括号来索引
Dialogue: 0,0:19:11.30,0:19:17.89,Default,,0,0,0,,当然也可以通过V0代他获取这个它的起始地
Dialogue: 0,0:19:18.38,0:19:27.96,Default,,0,0,0,,然后你一点size 就能获取它原本这个指定的大小,这样打包起来呢就能避免犯错
Dialogue: 0,0:19:28.62,0:19:53.10,Default,,0,0,0,,是不是,就这就是面向对象的分装思想,然后分装还有一个好处,就是有时候我们比如想把NV改成本来是爱的,我想改成四同源,那NV改成四步就行,还要同时调整一下分配的这个内存块的大小啊
Dialogue: 0,0:19:53.10,0:20:09.33,Default,,0,0,0,,所以C语言有一个real allow 函数,就可以把原来只有NNV的大小调整到4NV然后就它是先要复制给NV,然后再调整V就需要两个操作
Dialogue: 0,0:20:09.33,0:20:18.44,Default,,0,0,0,,但万一哪个程序员突然犯傻,他只复制了N1 ,但是没有给V更新,那就出错了
Dialogue: 0,0:20:18.44,0:20:32.78,Default,,0,0,0,,而 C++ 通过分装思想,就把两个操作合并为一个,它能够保证你只要你执行了这个操作,你前后不管放什么,我都不会出错
Dialogue: 0,0:20:32.78,0:20:40.54,Default,,0,0,0,,这就是有一种原子性的思想,就是我提供给你所有操作都是原子的
Dialogue: 0,0:20:40.54,0:20:44.98,Default,,0,0,0,,只要你不把这个原子切开,那我就没事
Dialogue: 0,0:20:44.98,0:20:54.32,Default,,0,0,0,,所以说这经常有一种叫data set 的模式,就是将获取器和设置器
Dialogue: 0,0:20:54.32,0:21:07.66,Default,,0,0,0,,也就是说这个resides 相当于sit size ,这个size 相当于get size ,就是设置它是一个函数,而不能直接V点sine 等于4
Dialogue: 0,0:21:07.66,0:21:11.79,Default,,0,0,0,,就是它这样就相当于我去hot 了
Dialogue: 0,0:21:11.79,0:21:20.06,Default,,0,0,0,,那个写入写入的时候,我会自动调整一下这个数字的那个内存
Dialogue: 0,0:21:20.42,0:21:28.59,Default,,0,0,0,,这时候就是代表它的读写函数,它是成员函数,这就是get settlement
Dialogue: 0,0:21:29.18,0:21:33.42,Default,,0,0,0,,然后当然你也不能就是说什么都要用
Dialogue: 0,0:21:33.42,0:21:39.53,Default,,0,0,0,,get saturday 去分装,比如三维矢量类,这个去分装是没意义的
Dialogue: 0,0:21:39.53,0:21:50.68,Default,,0,0,0,,为什么这个矢量类要分装,因为我写入NV之后,V也得重新改变,否则这个对象就变成一个错误状态
Dialogue: 0,0:21:50.68,0:22:03.26,Default,,0,0,0,,就是我内存只有两个,NV却说是就是我进行一个操作之后,如果是对象变成一个错误的状态,那才需要分装啊
Dialogue: 0,0:22:03.26,0:22:09.97,Default,,0,0,0,,而你再去设置一个MX,你设置它的X分量以后,这对象正确吗?
Dialogue: 0,0:22:09.97,0:22:15.65,Default,,0,0,0,,还是正确的呀,他们不会出现什么就是不变性叫什么
Dialogue: 0,0:22:15.65,0:22:21.33,Default,,0,0,0,,就是我改了一个之后,另一个也要改,这才是需要分装
Dialogue: 0,0:22:21.33,0:22:27.28,Default,,0,0,0,,你去分装一个三维使用率,还get x set x 这牛
Dialogue: 0,0:22:28.81,0:22:33.86,Default,,0,0,0,,这就是错误的那个滥用了面向对象思想
Dialogue: 0,0:22:33.86,0:22:45.95,Default,,0,0,0,,所以我建议就是像这种就直接一个strict ,然后三个成员就可以不要去get x 这样这样只会让你变得痛苦
Dialogue: 0,0:22:48.59,0:23:04.90,Default,,0,0,0,,然后除了刚刚说的这个不变性之外,他还有一个思想,就是他有一个叫销毁的过程,就是资源你分配了,那到时候离开的时候,你得销毁
Dialogue: 0,0:23:04.90,0:23:09.79,Default,,0,0,0,,在C语言中你可以用my lock ,然后是free 来释放
Dialogue: 0,0:23:09.79,0:23:25.24,Default,,0,0,0,,就是先是分配一个内存,然后分配了之后你得手动释放,但它不一样,它分配你只管分配它,到时候它能够自动判断是不是离开了这个函数
Dialogue: 0,0:23:25.24,0:23:35.00,Default,,0,0,0,,如果V就是临时定义在幂函数里的,所以幂函数一旦返回了,那这个V就会自动被释放
Dialogue: 0,0:23:35.00,0:23:39.88,Default,,0,0,0,,这个其实是它的一个特殊函数,叫结构函数
Dialogue: 0,0:23:39.88,0:23:51.46,Default,,0,0,0,,然后这个V初始化为四的呢就是一个构造函数,目标函数相当于mallock ,而结构函数相当于free
Dialogue: 0,0:23:51.46,0:23:56.61,Default,,0,0,0,,所以说这样也是为了避免程序犯错
Dialogue: 0,0:23:56.61,0:24:03.06,Default,,0,0,0,,就比如他忘记了释放这个内存,那不就出错了吗?
Dialogue: 0,0:24:05.05,0:24:12.89,Default,,0,0,0,,还有四点不要了,不要了,不要再new delete 了
Dialogue: 0,0:24:13.22,0:24:21.47,Default,,0,0,0,,new delete 和my lock free ,尽量不要再用,都用这个RAII指针去管理
Dialogue: 0,0:24:26.22,0:24:33.99,Default,,0,0,0,,唉,我稍微休息一下哦,马上回来哦,现在继续录啊
Dialogue: 0,0:24:35.13,0:24:43.96,Default,,0,0,0,,厕所疏通,哎,然后就是这个也是避免程序员犯错
Dialogue: 0,0:24:43.96,0:24:57.53,Default,,0,0,0,,这个思想是 C++ 他爸爸提出来的,叫资源获取及初始化,然后它还蕴含着一个资源释放就结构函数
Dialogue: 0,0:24:57.88,0:25:04.58,Default,,0,0,0,,然后这个RAIS想有什么好处的,避免犯错误
Dialogue: 0,0:25:04.58,0:25:08.50,Default,,0,0,0,,然后可能你觉得哎呀这这有什么吗?
Dialogue: 0,0:25:08.50,0:25:23.15,Default,,0,0,0,,我手动释放一下也很简单啊,你看一下这个例子,就是这个命有多个return ,然后这里面甚至还有一个文件的列表,你也去一个个去关闭吗?
Dialogue: 0,0:25:23.15,0:25:30.47,Default,,0,0,0,,就是你先打开一个文件,然后你说哎呀,F一是不是对着文件内容呀?
Dialogue: 0,0:25:30.47,0:25:37.27,Default,,0,0,0,,不是的话,F一得关闭,然后你开了F2 ,你忘记自己开了F1吗?
Dialogue: 0,0:25:37.27,0:25:45.37,Default,,0,0,0,,你得在这个退出的条件里也用一下F1close,F2close就你得去当心
Dialogue: 0,0:25:45.37,0:25:52.30,Default,,0,0,0,,当之前创建过哪些那个对象,你也得全部释放一遍
Dialogue: 0,0:25:54.90,0:26:08.09,Default,,0,0,0,,然后甚至有可能你是打开了一个列表式的文件,然后你打开很多个,你得用一个for 循环去把这个列表全部关掉才能退出
Dialogue: 0,0:26:09.12,0:26:25.80,Default,,0,0,0,,总之呢就是你非常麻烦,就是但是有II的话,你就可以知道这个只要管创建创建了之后销毁,它会自动帮你销毁
Dialogue: 0,0:26:25.80,0:26:43.42,Default,,0,0,0,,甚至如果你想提前销毁的话,比如我想把这个files 全部关掉,我不需要这样写,我只需要写files 点clear ,也就是把这个文件的那嗯数组长度设为零
Dialogue: 0,0:26:43.42,0:26:47.56,Default,,0,0,0,,那它这些文件不是引用就没了吗?
Dialogue: 0,0:26:47.56,0:26:50.82,Default,,0,0,0,,它会自动的销毁,对吧?
Dialogue: 0,0:26:50.82,0:27:01.42,Default,,0,0,0,,就是他是非常方便,就你轻松一个矢量也就能够自动关闭所有的文件
Dialogue: 0,0:27:02.49,0:27:09.60,Default,,0,0,0,,然后他就是除了 C++ 之外,还有很多是面向垃圾回收的语言
Dialogue: 0,0:27:09.60,0:27:11.78,Default,,0,0,0,,他们是怎么回事呢?
Dialogue: 0,0:27:11.78,0:27:18.90,Default,,0,0,0,,他们也是不需要自己去关闭,但是他是需要一段时间去关闭的
Dialogue: 0,0:27:19.26,0:27:29.35,Default,,0,0,0,,就是比如说他这个推进去以后,他退出了应用技术归0 ,但是这个归零不会立即删除
Dialogue: 0,0:27:29.35,0:27:38.29,Default,,0,0,0,,而是过一会儿时间会启动一个进程,把所有归零的都把它移除掉,然后关掉
Dialogue: 0,0:27:38.29,0:27:42.62,Default,,0,0,0,,但是这个对高性能计算而言就不行
Dialogue: 0,0:27:42.62,0:27:53.38,Default,,0,0,0,,他说我必须非常准确,比如这个mute x 的索引上锁与解锁,这个对时序是有要求的
Dialogue: 0,0:27:53.38,0:27:59.95,Default,,0,0,0,,也就是说如果我一号锁上了第二个人又锁上了
Dialogue: 0,0:27:59.95,0:28:10.61,Default,,0,0,0,,然后我们我是先锁一后锁二的,然后他是先锁二后锁一的,然后这两个人就永远卡死在那里,不会继续了
Dialogue: 0,0:28:10.61,0:28:13.59,Default,,0,0,0,,这就是一个著名的死守问题
Dialogue: 0,0:28:13.92,0:28:17.89,Default,,0,0,0,,然后II可以保证的是异常安全
Dialogue: 0,0:28:18.25,0:28:31.31,Default,,0,0,0,,也就是说比如在java 里有一个finally 语,又是他的功能是不管有没有发生异常,他这里都会被执,就是发生异常
Dialogue: 0,0:28:31.31,0:28:34.49,Default,,0,0,0,,我这connections 开了呀,也得关掉
Dialogue: 0,0:28:34.49,0:28:38.73,Default,,0,0,0,,我如果不发生异常,我还是得关掉connect
Dialogue: 0,0:28:39.06,0:28:54.59,Default,,0,0,0,,但是 C++ 又不需要烦恼了,他自己开出啊补货,那没事了,因为我这个文件开了以后,他扔出异常的同时,也会顺便关掉这个文件
Dialogue: 0,0:28:54.59,0:29:00.34,Default,,0,0,0,,所以这个文件里的内容会被顺利的写出来
Dialogue: 0,0:29:00.34,0:29:15.17,Default,,0,0,0,,可以看有一种病叫加拉病,是不是挺顺口的,总之它就是能够自动确保异常出异常的时候,它也能被自动释放
Dialogue: 0,0:29:15.17,0:29:19.34,Default,,0,0,0,,所以 C++ 就没有finally 这个语句了
Dialogue: 0,0:29:19.82,0:29:26.58,Default,,0,0,0,,然后就是我们的RAI刚才说到有构造函数和解构函数
Dialogue: 0,0:29:26.58,0:29:33.91,Default,,0,0,0,,那么如果我们要自定义类的话,应该总算明他们的构造函数呢
Dialogue: 0,0:29:33.91,0:29:41.81,Default,,0,0,0,,首先我们可以看到,就是如果我们这里写pack ,pack 就是定一个pack 变量
Dialogue: 0,0:29:41.81,0:29:55.35,Default,,0,0,0,,这时候其实是调用了一个没有参数的构造函数,然后就是在构造函数里呢,我们可以去初始化这些变量
Dialogue: 0,0:29:55.35,0:30:01.41,Default,,0,0,0,,然后就是我们这里默认的构造函数是无参的构造
Dialogue: 0,0:30:01.41,0:30:05.45,Default,,0,0,0,,以后我们这里打印就是name 是佩奇
Dialogue: 0,0:30:05.45,0:30:10.94,Default,,0,0,0,,wait 是80 ,就是这就是我们初始函数里产生的
Dialogue: 0,0:30:11.27,0:30:19.36,Default,,0,0,0,,如果没有这个构造函数的话,它就会打印出一个空的甚至是零
Dialogue: 0,0:30:22.59,0:30:34.90,Default,,0,0,0,,然后这里还有一个可以优化的点,就是他可以用这个语,就是这个叫初始化表达式,也就是用一个冒号
Dialogue: 0,0:30:34.90,0:30:44.45,Default,,0,0,0,,然后后面跟这个成员名括号里面写要初始化它的值,这样有一个什么好处呢?
Dialogue: 0,0:30:44.45,0:30:46.64,Default,,0,0,0,,首先就是他更高效
Dialogue: 0,0:30:46.64,0:30:55.67,Default,,0,0,0,,像这样的话呢,他是先把面目初始化为空,初始化为空,又去复制给了一给他一遍
Dialogue: 0,0:30:55.67,0:30:59.86,Default,,0,0,0,,佩奇就是他是初始化了两遍,对吧?
Dialogue: 0,0:30:59.86,0:31:03.34,Default,,0,0,0,,这样就比较低效,所以用冒号
Dialogue: 0,0:31:03.34,0:31:14.06,Default,,0,0,0,,然后后面通过这个成员的列表,用逗号隔开,就相当于在这个进入括号之前就把它初始化
Dialogue: 0,0:31:15.24,0:31:18.39,Default,,0,0,0,,这样的话呢就只用初始化一遍
Dialogue: 0,0:31:18.39,0:31:21.07,Default,,0,0,0,,然后还有一个什么好处呢?
Dialogue: 0,0:31:21.43,0:31:31.85,Default,,0,0,0,,周思,你如果这个name name 是一个没有无参构造函数的那这时候再这样写就会出错了
Dialogue: 0,0:31:33.29,0:31:35.39,Default,,0,0,0,,没人懂吗?
Dialogue: 0,0:31:38.60,0:31:59.90,Default,,0,0,0,,甚至孙佳佳还允许类成员为cos cos 它的属性它只能在这个初始化表达式进行一个初始化之后再初始化的话呢,就相当于再写入一个count 的变量,那就会出错了
Dialogue: 0,0:32:02.32,0:32:07.91,Default,,0,0,0,,好,被函数这个就是拷贝复制函数呀
Dialogue: 0,0:32:08.76,0:32:20.10,Default,,0,0,0,,拷贝函数可以呀,你就在这个配置拷贝函数就是这样,就是pack 它两个参数,一个是name ,一个sweet
Dialogue: 0,0:32:20.10,0:32:25.05,Default,,0,0,0,,那么这个时候就调用的是它拷贝构造函数
Dialogue: 0,0:32:25.05,0:32:37.45,Default,,0,0,0,,而如果你像那样用等号的话,这时候是拷贝赋值函数,因为它已经先进行了一波空初始化之后再去复制给他
Dialogue: 0,0:32:37.45,0:32:43.44,Default,,0,0,0,,这是两步,操作,效率就更低了,明白了吗?
Dialogue: 0,0:32:44.54,0:32:58.59,Default,,0,0,0,,然后就是我们刚才说这个可以添加构造函数的参数,然后调用的时候呢,这里就不要空了,就给他一个括号,然后里面写的是参数
Dialogue: 0,0:32:58.59,0:33:04.06,Default,,0,0,0,,然后如果括号里面你不想给他参数,那就不要括号
Dialogue: 0,0:33:04.06,0:33:09.00,Default,,0,0,0,,如果你写括号,他会认为你是一个函数声明了
Dialogue: 0,0:33:09.00,0:33:20.56,Default,,0,0,0,,所以说要么有括号,要么没括号,就是你这样,然后这样也会初始化得到佩奇80
Dialogue: 0,0:33:21.27,0:33:39.29,Default,,0,0,0,,然后我们还可以就是除了可以有多个构造函数参数,还可以有一个一个的时候就是括号80 ,然后这个就会传到未成,然后初始化的表达式呢也可以弄得复杂一点
Dialogue: 0,0:33:39.29,0:33:50.79,Default,,0,0,0,,比如一只重达80公斤的猪,然后这个作为它的名字,这时候名字就会变成这个,然后体重呢也会变成80
Dialogue: 0,0:33:51.84,0:34:02.26,Default,,0,0,0,,然后two strain 就是把80转换为字符串的80 ,你直接拿字符串跟80相加是会出错的
Dialogue: 0,0:34:02.26,0:34:09.80,Default,,0,0,0,,先要把它转换为字符串,就是用这个里面的数据函数才能相加
Dialogue: 0,0:34:12.09,0:34:17.16,Default,,0,0,0,,然后这个单个参数有一个什么坑人的地方呢?
Dialogue: 0,0:34:17.16,0:34:32.45,Default,,0,0,0,,就是就是你甚至可以把pad 等于80 ,你就是如果它只有一个参数,可以改用这个语法,这个语法就就感觉好像配的是一个整形数一样
Dialogue: 0,0:34:32.45,0:34:40.75,Default,,0,0,0,,如果你不需要不想把配合当成一个整形数,你可以用这个语法explicit panel
Dialogue: 0,0:34:40.75,0:35:00.26,Default,,0,0,0,,也就是说我加了不加,这个是隐私的构造,加了就是显示的,你必须显示的用一个大括号才能表明我的确是要构造函数,而这个呢就会被认为是隐私的调用构造函数
Dialogue: 0,0:35:00.26,0:35:10.36,Default,,0,0,0,,从而他看到这是显示的,然后就是他就会出错,这样就能帮助我们避免一些坑之类的
Dialogue: 0,0:35:11.81,0:35:16.58,Default,,0,0,0,,然后还有什么地方会导致这个陷阱呢?
Dialogue: 0,0:35:16.58,0:35:25.29,Default,,0,0,0,,就是如果我比如刚才这个分装成一个秀函数,然后秀函数的参数是一只猪
Dialogue: 0,0:35:25.70,0:35:34.02,Default,,0,0,0,,如果我们没有这个explicit 这个修饰的话,我直接写秀括号80是可以的
Dialogue: 0,0:35:34.35,0:35:43.32,Default,,0,0,0,,就是它会自动把80转换到pad 而不会报错,这样的话就很坑了
Dialogue: 0,0:35:43.32,0:35:56.55,Default,,0,0,0,,就比如我本来以为就是有一个接受int 参数的,结果我没有接变成in 的参数,反而变成一只猪的打印了,这样就容易出错
Dialogue: 0,0:35:56.55,0:36:06.54,Default,,0,0,0,,就特别一个例子,就是victim ,就是刚才不是说victor 可以接受一个,比如四个作为它的大小吗?
Dialogue: 0,0:36:06.54,0:36:16.26,Default,,0,0,0,,那这样我一个函数接收一个rector ,我给它输入一个四,那它自动变成一个四大小的victor
Dialogue: 0,0:36:16.26,0:36:27.75,Default,,0,0,0,,就我本来想要一个,嗯,总之就是不能让他太智能,有什么问题吗?
Dialogue: 0,0:36:29.35,0:36:31.13,Default,,0,0,0,,有问题吗?
Dialogue: 0,0:36:32.57,0:36:34.60,Default,,0,0,0,,没问题,我们继续
Dialogue: 0,0:36:34.60,0:36:43.90,Default,,0,0,0,,所以我推荐就是如果你不你的这个int 和pad 没什么关系的话,都要加上explanation
Dialogue: 0,0:36:44.44,0:36:56.13,Default,,0,0,0,,然后x flash 的通常教科书上说只有单参数需要,其实多参数这个x blessed 也有用,它体现在哪呢?
Dialogue: 0,0:36:56.13,0:37:08.96,Default,,0,0,0,,就是我们有一个这个语法,就是除了可以用pack 括号80 ,也可以用这个花括号,甚至花括号前面还可以写个等号
Dialogue: 0,0:37:08.96,0:37:15.38,Default,,0,0,0,,然后这个等号就会被认为是隐私的考隐私的构造函数
Dialogue: 0,0:37:15.38,0:37:20.96,Default,,0,0,0,,但是如果我们加上explanation 的话,这里就会出错了
Dialogue: 0,0:37:21.72,0:37:36.71,Default,,0,0,0,,然后还有作为函数参数的时候,我们如果是没有explanation 的话,也可以直接秀括号,然后里面写一个花括号,然后配齐就不需要一个配的
Dialogue: 0,0:37:36.71,0:37:44.34,Default,,0,0,0,,但如果有的时候我们绣有多个重载,那这时候写这个就很容易混淆
Dialogue: 0,0:37:44.34,0:37:52.79,Default,,0,0,0,,所以说这时候如果你还是需要不想用这个单个括号的话,就可以用explanation
Dialogue: 0,0:37:52.79,0:37:58.24,Default,,0,0,0,,比如就是作为返回值的时候,就我们可以很方便
Dialogue: 0,0:37:58.24,0:38:04.51,Default,,0,0,0,,如果你不想要这个方便,也加上explanation 就行了,有问题吗?
Dialogue: 0,0:38:06.79,0:38:10.39,Default,,0,0,0,,对对对,多个参数也有这个陷阱
Dialogue: 0,0:38:13.26,0:38:22.89,Default,,0,0,0,,但是这个线你就不那么明显,就是单个参数的限定体现在就是没有一个花括号,它都能够进行类型转换
Dialogue: 0,0:38:22.89,0:38:28.72,Default,,0,0,0,,而多个的话你得一个花括号,然后用逗号隔开,它才能出现陷阱
Dialogue: 0,0:38:28.72,0:38:32.09,Default,,0,0,0,,所以一般来说都是避免单个的陷阱
Dialogue: 0,0:38:32.62,0:38:40.51,Default,,0,0,0,,然后就是提到刚才这两个都是显示的,只有这个是隐私
Dialogue: 0,0:38:40.51,0:38:43.51,Default,,0,0,0,,那为什么要区分这两个呢?
Dialogue: 0,0:38:43.51,0:38:47.88,Default,,0,0,0,,就是他们都是调用显示的那有啥区别?
Dialogue: 0,0:38:47.88,0:38:56.62,Default,,0,0,0,,就是有一个很大的区别,就是比如it 括号用括号调用的显示,它是不会出错的
Dialogue: 0,0:38:56.62,0:39:00.99,Default,,0,0,0,,也就是你可以把一个浮点数变成整数
Dialogue: 0,0:39:00.99,0:39:07.00,Default,,0,0,0,,然后但是如果你用花括号,它就是一个更安全的转换
Dialogue: 0,0:39:07.00,0:39:08.91,Default,,0,0,0,,为什么更安全呢?
Dialogue: 0,0:39:08.91,0:39:18.20,Default,,0,0,0,,就是因为浮点数它转换到int ,比如3.14会转换成3 ,这时候不是丢失精度了嘛
Dialogue: 0,0:39:18.20,0:39:25.57,Default,,0,0,0,,然后他编译器就认为这个是一个会丢失精度的转换,它就会出错
Dialogue: 0,0:39:25.57,0:39:37.66,Default,,0,0,0,,但是反过来,如果我写float float 括号3 ,这样从int 转换成float 通常都是不会丢失精度的,这就会通过
Dialogue: 0,0:39:37.66,0:39:42.50,Default,,0,0,0,,但反过来,如果float 转换成int 就会出错
Dialogue: 0,0:39:43.10,0:39:52.32,Default,,0,0,0,,而如果你用int 括号3.14的话,这时候他不认不管了,他始终能够成功转换
Dialogue: 0,0:39:52.32,0:39:52.61,Default,,0,0,0,,他
Dialogue: 0,0:39:52.61,0:40:00.96,Default,,0,0,0,,这是考虑兼容C语言和 C++ 98 ,所以才保留下来的一个历史遗留
Dialogue: 0,0:40:00.96,0:40:04.14,Default,,0,0,0,,对对对,就是不允许那种case
Dialogue: 0,0:40:04.97,0:40:12.41,Default,,0,0,0,,然后就是这个因为是然后除了这个int 括号以外,pig 括号也会有区别
Dialogue: 0,0:40:12.41,0:40:17.19,Default,,0,0,0,,就是我们刚才还以为这两个是一样的,对吧?
Dialogue: 0,0:40:17.19,0:40:27.83,Default,,0,0,0,,就是如果你把这里改成84.0 ,然后这里改成84.0 ,那下一个就不会出错,上一个就会出错
Dialogue: 0,0:40:27.83,0:40:37.40,Default,,0,0,0,,所以如果你想要保证安全,不会产生这种就是narrow case 的话,就可以尽量多用这个花括号
Dialogue: 0,0:40:37.40,0:40:48.48,Default,,0,0,0,,然后谷歌公司他也说他们有一个代码规范,就是说永远不要用这个圆括号了
Dialogue: 0,0:40:48.48,0:41:03.67,Default,,0,0,0,,如果你需要就强制类型转换,就是比如想把flow 转为int ,可以用status cast int ,而不是直接写int ,这样它就能保证一个什么安全
Dialogue: 0,0:41:03.67,0:41:15.45,Default,,0,0,0,,就比如我想要把in 的转换为指针static case 就会失败,因为它指针和int 是不一定有任何关联的
Dialogue: 0,0:41:15.45,0:41:24.44,Default,,0,0,0,,而如果你实在是需要转换的话,也可以用rainbow cast ,它,就是相当于better cast
Dialogue: 0,0:41:24.44,0:41:24.75,Default,,0,0,0,,它
Dialogue: 0,0:41:24.75,0:41:29.71,Default,,0,0,0,,不管你内容是什么,它就是按位置转换
Dialogue: 0,0:41:29.71,0:41:39.44,Default,,0,0,0,,就是就比如我的那个零XB800 ,这是某八六上一个就是输出控制台的地址
Dialogue: 0,0:41:39.44,0:41:49.18,Default,,0,0,0,,我想要把这个地址直接转换为一个指针,就可以用reinterpret c 语言的话是用这个语法
Dialogue: 0,0:41:49.18,0:41:58.11,Default,,0,0,0,,所以就是用通过指明这个什么类型的cast ,这样就更更加明确了,就不容易出现
Dialogue: 0,0:41:58.11,0:42:07.85,Default,,0,0,0,,比如it 里面写了一个指针的P我还不知道它的指针,然后编译器也不报错就容易出错
Dialogue: 0,0:42:07.85,0:42:11.64,Default,,0,0,0,,但是如果你用static case ,它就会报错
Dialogue: 0,0:42:11.64,0:42:20.31,Default,,0,0,0,,虽然就是我其实在ZNO中经常用这样写,但是其实是一个不好的习惯
Dialogue: 0,0:42:20.31,0:42:25.10,Default,,0,0,0,,谷歌也说了,不要用嗯,有什么问题吗?
Dialogue: 0,0:42:26.03,0:42:28.08,Default,,0,0,0,,没问题继续啊
Dialogue: 0,0:42:28.60,0:42:36.63,Default,,0,0,0,,然后其实就是我刚才说我们可以自定义一个无参构造函数
Dialogue: 0,0:42:36.63,0:42:46.52,Default,,0,0,0,,但其实如果你不写构造函数的话,编译器会自动去生成一个无参的,这是为什么呢?
Dialogue: 0,0:42:46.52,0:42:56.81,Default,,0,0,0,,就是为了兼容C语言,就是C语言经常就是没有构造函数这个概念的,他们也会直接写pig pig
Dialogue: 0,0:42:56.81,0:43:04.97,Default,,0,0,0,,所以说为了兼容C语言,如果你没写构造函数,它会默认生成一个空的构造函数
Dialogue: 0,0:43:04.97,0:43:07.69,Default,,0,0,0,,这构造函数你会做什么呢?
Dialogue: 0,0:43:07.69,0:43:15.85,Default,,0,0,0,,就是只要你这里面每一个有构造函数,无参构造函数的,它会每一个去调用一遍
Dialogue: 0,0:43:15.85,0:43:22.63,Default,,0,0,0,,但是它有一个陷阱,什么陷阱它也是为了兼容性考虑的陷阱
Dialogue: 0,0:43:22.63,0:43:38.69,Default,,0,0,0,,就是如果你的类型是一个int 类型或者float 这种基础类型,或者是一个指针类型,或者是由这些类型组成的试卷,可能他会认为你是一个原始的旧的数据
Dialogue: 0,0:43:38.69,0:43:40.51,Default,,0,0,0,,为什么原始旧呢?
Dialogue: 0,0:43:40.51,0:43:46.47,Default,,0,0,0,,就是为了兼容C语言,就是你们C语言都是原始的旧的
Dialogue: 0,0:43:46.47,0:43:51.13,Default,,0,0,0,,然后他就说你们的东西我是不会初始化的
Dialogue: 0,0:43:51.13,0:43:55.80,Default,,0,0,0,,如果你想要初始化的话,可以加一个括号0
Dialogue: 0,0:43:55.80,0:44:04.61,Default,,0,0,0,,就代表说哎呀,虽然这是一个C语言的类型,但我还是想将它初始化为零就可以了
Dialogue: 0,0:44:05.15,0:44:11.55,Default,,0,0,0,,就如果你这里不写初始化的话,这是C语言的类型,它不会初始化
Dialogue: 0,0:44:11.55,0:44:17.25,Default,,0,0,0,,然后这样你去传给它的话,它其实会变成一个随机初始化
Dialogue: 0,0:44:17.25,0:44:23.90,Default,,0,0,0,,就是内存中原来这块占上这个地方是什么值,它就原来还是什么值
Dialogue: 0,0:44:24.45,0:44:31.14,Default,,0,0,0,,对对对啊对啊,就是他这就会变成一个随机初始化了
Dialogue: 0,0:44:31.14,0:44:43.02,Default,,0,0,0,,所以我们最好还是给他打上一个括号,有这些类型in the float double 指针,这些最好给它初始化一
Dialogue: 0,0:44:43.35,0:44:51.32,Default,,0,0,0,,这样的话呢它就能够在编译器自动的构造函数里面去把它初始化为零了
Dialogue: 0,0:44:53.49,0:45:06.55,Default,,0,0,0,,然后还有一种就是就是我们当然也可以自己去定义一个函数,但是定义了函数之后,它这个括号零也是有效的
Dialogue: 0,0:45:06.55,0:45:14.96,Default,,0,0,0,,就是不管是编译器默认生成的还是用户自定义的这个东西都始终是有效的
Dialogue: 0,0:45:17.02,0:45:19.19,Default,,0,0,0,,怎么样明白了吗?
Dialogue: 0,0:45:19.52,0:45:33.26,Default,,0,0,0,,就是他这个就所以我推荐就是你们在第一类的时候,始终在这些初始C语言类型后面加个括号0 ,就可以避免一些错误
Dialogue: 0,0:45:33.81,0:45:42.04,Default,,0,0,0,,然后他还除了可以用单括号后面直这种语法之外,它还可以有用等号
Dialogue: 0,0:45:42.04,0:45:54.73,Default,,0,0,0,,就比如inter m weight 等于80 ,这和括号80是1样的,除了它不能用丢失,除了他必须不能用explanation 的以外
Dialogue: 0,0:45:54.73,0:46:09.32,Default,,0,0,0,,就是比如我这里有一个explanation ,但是有两个参数的demo 类,它的构造函数是可以在pig 类里面这样通过花括号去调用的,但用这个就不行
Dialogue: 0,0:46:09.32,0:46:21.91,Default,,0,0,0,,因为还是因为我用了explanation ,这个加一个等号,他就认为是眼显眼啊,不是不是,你认为是影视的构造,它就初创
Dialogue: 0,0:46:22.26,0:46:25.36,Default,,0,0,0,,明白了吗?
Dialogue: 0,0:46:28.43,0:46:39.63,Default,,0,0,0,,然后除了这个之外,就除了可以括号零去初始化,还可以通过inter x 括号里什么也不写也能初始化
Dialogue: 0,0:46:39.63,0:46:47.29,Default,,0,0,0,,但如果你括号这个括号都不写的话,它就不会说实话,它是随机的值
Dialogue: 0,0:46:47.29,0:46:57.13,Default,,0,0,0,,就是所以我建议就所有这种基础类型后面都加一个花括号,就可以避免它出现随机数
Dialogue: 0,0:46:57.13,0:47:10.52,Default,,0,0,0,,还有就是也可以直接出来这里写一个int 挂括号,这个其实和零是等价的,就代表int 类型的零初始化当然是整形的零了
Dialogue: 0,0:47:10.52,0:47:16.81,Default,,0,0,0,,如果是浮点数的话,就比如float 发括号就会打印出0.0
Dialogue: 0,0:47:17.25,0:47:28.29,Default,,0,0,0,,当然指针的话如果一个画括号空的,就相当于把他出手化为空指针了,怎么办?
Dialogue: 0,0:47:29.82,0:47:58.56,Default,,0,0,0,,然后这个其实就是 C++ 11新增的功能,然后 C++ 11还有一个什么很牛的功能,就是就是你甚至不需要像刚才那样,你甚至不需要去写这个函数,它自动会生成一个这个函数,就是它呃它能够它能够呃就是比如我这里是一个构造函数没写
Dialogue: 0,0:47:58.56,0:48:02.58,Default,,0,0,0,,但它其实已经有这两个构造函数了
Dialogue: 0,0:48:02.93,0:48:14.38,Default,,0,0,0,,就是比如括号配齐80 ,它会自动有一个pack 支持两个参数的那个它分别会初始化到m name 和m wait
Dialogue: 0,0:48:14.38,0:48:23.82,Default,,0,0,0,,但是如果你用的C加11这个新增的构造函数,它是不能通过括号来调用的
Dialogue: 0,0:48:23.82,0:48:28.12,Default,,0,0,0,,这个是为了兼容 C++ 98之类的
Dialogue: 0,0:48:30.87,0:48:47.76,Default,,0,0,0,,对呀,括号和这个括号是一样的,除了它不能支持这个变载转换,对你可以认为int 的默认构造函数是初始化为零
Dialogue: 0,0:48:50.52,0:49:01.47,Default,,0,0,0,,然后就是 C++ 11以后,你就不需要写一遍构造函数,它自动就能够认为你十二初始化给佩奇
Dialogue: 0,0:49:01.47,0:49:07.08,Default,,0,0,0,,然后除了你可以全部指定之外,你也可以指定部分
Dialogue: 0,0:49:07.08,0:49:15.89,Default,,0,0,0,,你只要在page 里这里写最后一个m wait 为零的话,这就代表m wait 有一个默认值是零
Dialogue: 0,0:49:15.89,0:49:24.70,Default,,0,0,0,,然后这第一个我这用户只指定了一个配齐,那就会给到name ,然后这里没有写80
Dialogue: 0,0:49:24.70,0:49:28.71,Default,,0,0,0,,那好啊,那我这里不是写括号零了吗?
Dialogue: 0,0:49:28.71,0:49:31.38,Default,,0,0,0,,那它就会自动默认为零
Dialogue: 0,0:49:31.38,0:49:39.40,Default,,0,0,0,,然后 C++ 20其实还可以通过点m wait 来跳过m name ,直接初始化m wait
Dialogue: 0,0:49:39.75,0:49:49.12,Default,,0,0,0,,不过如果你这里没有括号0 ,而这里也没有的话,那这里的mam weight 就会变成一个随机数
Dialogue: 0,0:49:50.54,0:49:54.92,Default,,0,0,0,,顺序要求的要顺序的就是m name m wait
Dialogue: 0,0:49:54.92,0:50:03.80,Default,,0,0,0,,如果你这两个反一反,这里就出错,也得反一反,不行不行,不能打乱
Dialogue: 0,0:50:03.80,0:50:10.10,Default,,0,0,0,,这个只有在 C++ 20中才可以通过点m wait 才能打乱
Dialogue: 0,0:50:10.10,0:50:18.64,Default,,0,0,0,,但是 C++ 17你是不能打乱的,还有问题吗?
Dialogue: 0,0:50:19.12,0:50:21.12,Default,,0,0,0,,我先治口水啊
Dialogue: 0,0:50:28.40,0:50:32.40,Default,,0,0,0,,然后初始化列表就不是很方便吗?
Dialogue: 0,0:50:32.73,0:50:40.92,Default,,0,0,0,,再结合我们刚刚说的,没有explanation 的这一点,就可以做这个操作
Dialogue: 0,0:50:40.92,0:51:07.10,Default,,0,0,0,,就是我们图形学不是有一个光线追踪嘛,然后光线追踪有一个intercept 函数,它是要返回是否命中啊,命中了什么地方啊,然后命中点的法线是多少啊,命中光线传了多少升啊,就是它是有多个返回值的,那一般都是怎么解决呢?
Dialogue: 0,0:51:07.10,0:51:18.09,Default,,0,0,0,,第一种是C语言的方式,就是让interesting 很接受多个参数的指针,比如成p heat ,recent 3层ppose
Dialogue: 0,0:51:18.09,0:51:24.86,Default,,0,0,0,,然后再返回的时候把P全部去复制一遍才能去返回
Dialogue: 0,0:51:24.86,0:51:41.17,Default,,0,0,0,,但是我们 C++ 里面可以直接返回一个strict 类,这时候就可以auto head 等internet 就可以让他直接去返回一个具有多个属性的那个类
Dialogue: 0,0:51:41.17,0:51:47.33,Default,,0,0,0,,然后之后呢也可以用head 点去访问它的所有属性
Dialogue: 0,0:51:47.33,0:52:08.25,Default,,0,0,0,,当然我们这里这个初始化列表有一个方面之处,就是你不需要在这里重复一遍hat raise ,然后一个个去设置了,你直接在这里写一下跨括号就可以自动让children hand origin
Dialogue: 0,0:52:08.25,0:52:34.50,Default,,0,0,0,,对pos 带来问题,对农就一个个顺序的去复制给他,甚至连head rise 都不像,甚至直接是这样的卡,然后intersect 就可以自动把这个没有名字的strict 作为它的返回类型作业会会嗯,这期的作业不会讲,下期下期会讲
Dialogue: 0,0:52:34.50,0:52:51.08,Default,,0,0,0,,这一期的作业比较简单,嗯,然后就是这样的话呢,就是还有一种做法不是trouble 嘛,但返回trouble 的话就是你前后的顺序它是没有名字的
Dialogue: 0,0:52:51.08,0:52:59.61,Default,,0,0,0,,就你不能hat 点hat 或者hat 点pos ,就必须用STDget ,或者用这个structure binding
Dialogue: 0,0:52:59.61,0:53:07.00,Default,,0,0,0,,但这样没有顺序,你万一不小心把pos 和logo 写反了,他也不会出错
Dialogue: 0,0:53:07.00,0:53:14.96,Default,,0,0,0,,然后你就抱着这个错的数据,而这个有名字的话呢,就不容易搞错了
Dialogue: 0,0:53:16.37,0:53:24.21,Default,,0,0,0,,然后它除了可以用于返回值更加方便,它还可以用于让参数更加方便
Dialogue: 0,0:53:24.21,0:53:39.64,Default,,0,0,0,,就参数我们不是说这个默认生成初始化列表是一个隐私的嘛,就是他不需要再用这个指明一遍类型了,就放可不是有这个类型签名了吗?
Dialogue: 0,0:53:39.64,0:53:55.16,Default,,0,0,0,,你只要写一遍这个括号,它自动能帮你转换到这个这个非常非常长的类型,就不需要再写一遍了,就只需要写括号,我已经知道它是什么类型了
Dialogue: 0,0:53:55.16,0:53:58.60,Default,,0,0,0,,然后当然C加S7也引入CTAD
Dialogue: 0,0:53:58.60,0:54:05.26,Default,,0,0,0,,所以即便你需要,你也不需要指定这个间括号里的模板参数
Dialogue: 0,0:54:07.28,0:54:23.79,Default,,0,0,0,,然后还有一个就是有时候我们自定义了构造函数,因为一旦自定义了构造函数之后,编译器就不会再生成默认的无参构造函数
Dialogue: 0,0:54:23.79,0:54:41.15,Default,,0,0,0,,所以说如果我定义了自定义构造函数之后,还想让编译器去生成午餐的话,就可以用等于default 去恢复它变异器让它去还是去生成默认的构造函数
Dialogue: 0,0:54:41.15,0:54:47.30,Default,,0,0,0,,就是可以看到如果没有这一行的话,它这个就没有了
Dialogue: 0,0:54:47.30,0:54:54.58,Default,,0,0,0,,所以我们通过default 之后,还是可以回到name 为空,然后为零的状态
Dialogue: 0,0:54:55.84,0:55:00.08,Default,,0,0,0,,有路不,你看一下我空间里呀
Dialogue: 0,0:55:02.29,0:55:11.67,Default,,0,0,0,,不过就是刚才说很方便,这个是好像没办法通过,等于点bot 来恢复了
Dialogue: 0,0:55:12.54,0:55:18.85,Default,,0,0,0,,我也不知道为什么有可能他写起来没办法写出来
Dialogue: 0,0:55:22.52,0:55:34.57,Default,,0,0,0,,然后除了这个可以生成那个无参的之外,编译器还会生成一个类型为这个的构造函数
Dialogue: 0,0:55:34.57,0:55:44.33,Default,,0,0,0,,它的功能就是从另一个里面拷贝到当前对象,它的名字叫做拷贝构造函数
Dialogue: 0,0:55:44.33,0:55:56.43,Default,,0,0,0,,它的功能就是在我调用pack 2等于pack 的时候就会调用这个它的功能就是把每一个属性都拷贝一遍
Dialogue: 0,0:55:57.04,0:56:04.03,Default,,0,0,0,,就比如派个二等于派个这个和这个这样方式去调用是等价的
Dialogue: 0,0:56:04.36,0:56:14.50,Default,,0,0,0,,然后它它调用起来之后,我们也可以去自定义,就是编译器生成的和这个是一样的
Dialogue: 0,0:56:14.50,0:56:30.53,Default,,0,0,0,,就是把other 的m name 拷贝到我的m name ,然后把二代的M位置拷贝为我的M这是我们自定义的拷贝函数,调用方式也是一样
Dialogue: 0,0:56:30.89,0:56:44.17,Default,,0,0,0,,然后如果我不想让他就是这个有一个特点,就是即使我定义了自定义的构造函数,它的拷贝函数也是不会被删除的
Dialogue: 0,0:56:44.17,0:56:51.22,Default,,0,0,0,,如果想要让它不要再生成拷贝了,我们可以用等于点net 去删除
Dialogue: 0,0:56:51.22,0:56:58.00,Default,,0,0,0,,这个就和default 是让它去生成delete 是不要生成它们是相对的
Dialogue: 0,0:56:58.00,0:57:18.79,Default,,0,0,0,,如果你不确定一个函数有没有生成,就可以显示的去声明一下你想要default 还是然后除了这个拷贝之外,其实还有一个是operator 等于它是什么作用呢?
Dialogue: 0,0:57:18.79,0:57:32.38,Default,,0,0,0,,它的作用就是这个是拷贝,就是我在pack pack 定义的时候写一个等号,然后拷贝就是我已经定义了一个,我后期再给它去赋值
Dialogue: 0,0:57:32.38,0:57:38.90,Default,,0,0,0,,这时候它就调用了这个形式的函数,它叫做拷贝复制函数
Dialogue: 0,0:57:38.90,0:57:50.05,Default,,0,0,0,,但是拷贝呢它意味着我已经是先构造一遍,然后再复制的啊,构造的话就是直接在原来对象上构造
Dialogue: 0,0:57:50.05,0:57:55.21,Default,,0,0,0,,所以说这两个之间其实拷贝构造是更高效的
Dialogue: 0,0:57:55.21,0:58:00.38,Default,,0,0,0,,如果你需要灵活性才是需要去拷贝赋值函数
Dialogue: 0,0:58:04.32,0:58:09.81,Default,,0,0,0,,然后为什么这个拷贝够复制函数返回的配置和呢?
Dialogue: 0,0:58:09.81,0:58:20.79,Default,,0,0,0,,就是为了返回一个pack 的引用,从而支持连等号,也就是它可以链式的调用,比如A等于B等于C这样子
Dialogue: 0,0:58:24.69,0:58:34.35,Default,,0,0,0,,然后除了拷贝构造和拷贝复制,还有移动构造和移动复制,以及它还会生成一个结构函数
Dialogue: 0,0:58:34.35,0:58:47.96,Default,,0,0,0,,这个在其他语言中都没有这么复杂,就其他语言可能只有默认构造函数和结构函数,但没有这么多拷贝啊移动之类的概念
Dialogue: 0,0:58:47.96,0:58:51.17,Default,,0,0,0,,那这些东西是干什么用的呢?
Dialogue: 0,0:58:51.17,0:59:02.11,Default,,0,0,0,,我们待会再说,然后就是默认情况下,这些函数都是这个状态,就是拷贝它是把每个属性拷贝一遍
Dialogue: 0,0:59:02.11,0:59:11.71,Default,,0,0,0,,赋值是把每个属性赋值一遍,然后移动是把每个属性移动一遍,移动用我们的STDmove
Dialogue: 0,0:59:11.71,0:59:13.85,Default,,0,0,0,,但这函数是什么呢?
Dialogue: 0,0:59:13.85,0:59:25.43,Default,,0,0,0,,它我们稍后再说,这拷贝是默认都是深拷贝,只有智能指针的拷贝是前拷贝
Dialogue: 0,0:59:25.43,0:59:38.05,Default,,0,0,0,,就是比如victor 这种就是它的拷贝都是就 C++ 有一个规定,就是除非你是智能指针,否则始终用生烤
Dialogue: 0,0:59:38.71,0:59:49.54,Default,,0,0,0,,所以说有的类它会去删除拷贝构造函数,然后让智能指针管理这个类
Dialogue: 0,0:59:49.54,1:00:23.66,Default,,0,0,0,,这样这个类的拷贝就变成智能指针的前拷贝了,就可以避免那个浪费那个拷贝所需的时间啊,你已经学会了构造函数了,但是还没完,就是呃我先休息一下哦,我喝口水就马上回来哦,看一看继续录啊
Dialogue: 0,1:00:24.92,1:00:30.15,Default,,0,0,0,,然后就是我们刚才不是学会了构造函数吗?
Dialogue: 0,1:00:30.15,1:00:37.13,Default,,0,0,0,,那我们来自己实现一个victory ,来看看构造函数学的好不好
Dialogue: 0,1:00:38.65,1:00:52.60,Default,,0,0,0,,首先我们定义了一个vector 括号NN代表要分配的大小,然后就把我们C语言所说的两个那个两个属性分装为一个
Dialogue: 0,1:00:52.60,1:01:05.10,Default,,0,0,0,,首先是要大小,然后大小我们初始化为用户指定的大小,然后内存分配为用户指定的这个大小乘以我们这个类型的大
Dialogue: 0,1:01:05.43,1:01:12.68,Default,,0,0,0,,然后结构的时候呢,也就是离开这个命函数作用域的时候会被调用
Dialogue: 0,1:01:12.68,1:01:22.21,Default,,0,0,0,,我们当然是选择free 这个data 啦,然后resides 也是我们刚刚提到C语言的realize
Dialogue: 0,1:01:22.21,1:01:43.83,Default,,0,0,0,,然后还有一个运算符存在函数operator ,括号oppo a 它就代表当我调用这个方啊,不不不不不方括号的时候,它就会调用到这个函数,它就代表会返回m data 的第index 个元素
Dialogue: 0,1:01:43.83,1:01:51.65,Default,,0,0,0,,就它使用起来就和指针一模一样,然后塞子会返回B的大小
Dialogue: 0,1:01:51.65,1:01:54.78,Default,,0,0,0,,那这里面有什么问题呢?
Dialogue: 0,1:01:54.78,1:02:06.05,Default,,0,0,0,,首先最明显的问题就是这里没有explanation ,就我甚至可以V等于二这样子去写就很危险
Dialogue: 0,1:02:06.84,1:02:14.73,Default,,0,0,0,,但是他的确工作了,就是他的确能用有4加3加2加1 ,它是能用的
Dialogue: 0,1:02:14.73,1:02:22.34,Default,,0,0,0,,但它其实有很多陷阱,一个是explanation 的美甲,第二个就是三无法则
Dialogue: 0,1:02:22.34,1:02:29.38,Default,,0,0,0,,也就是刚才我们提到的一些问题,就是前人总结了一个规律
Dialogue: 0,1:02:29.38,1:02:37.28,Default,,0,0,0,,就是如果你定义了结构函数,那你必须定义或删除拷贝和拷贝赋值
Dialogue: 0,1:02:37.61,1:02:43.55,Default,,0,0,0,,如果你定义了拷贝构造,那你最好还要定义拷贝赋值
Dialogue: 0,1:02:43.55,1:02:48.42,Default,,0,0,0,,如果你定义移动构造,最好还要定移动赋值
Dialogue: 0,1:02:48.42,1:02:57.88,Default,,0,0,0,,如果你定义拷贝构造和拷贝副词,那你为了效率最好还是定义移动构造和移动赋值
Dialogue: 0,1:02:57.88,1:03:09.83,Default,,0,0,0,,然后这里有一个网站,有很多这样的规则,你可以去看一下,它可以避免你的这个这些常见的错误
Dialogue: 0,1:03:09.83,1:03:16.95,Default,,0,0,0,,就是这些函数里他这些都是编译器会默认生成的
Dialogue: 0,1:03:16.95,1:03:24.29,Default,,0,0,0,,然后就是如果我们刚刚victoria 是没有定义拷贝构造函数,对吧?
Dialogue: 0,1:03:24.29,1:03:32.90,Default,,0,0,0,,但是它其实已经默认生成了它的拷贝,就是指针的前拷贝,它是全拷贝
Dialogue: 0,1:03:32.90,1:03:39.94,Default,,0,0,0,,然后这样复制指针以后,它再去解构的时候,它会解构两遍
Dialogue: 0,1:03:39.94,1:03:54.03,Default,,0,0,0,,也就是说我是前拷贝,然后还是调用了两遍,对一个指针调用两次福利,那就是double 福利,也就是一个资源释放了两次
Dialogue: 0,1:03:55.23,1:04:03.37,Default,,0,0,0,,也就是说就是如果我的拷贝是前拷贝的话,是不能直接去定义结构函数的
Dialogue: 0,1:04:03.37,1:04:10.73,Default,,0,0,0,,这就是为什么他说我有结构函数的话,就必须定义或删除拷贝构造
Dialogue: 0,1:04:10.73,1:04:14.93,Default,,0,0,0,,因为默认的拷贝构造是一个浅拷贝呀
Dialogue: 0,1:04:14.93,1:04:23.34,Default,,0,0,0,,浅拷贝了之后,那就出现了两个指针需要解构,那就会出现双重福利就会出错
Dialogue: 0,1:04:23.34,1:04:30.96,Default,,0,0,0,,甚至更危险的是V2减够了,而V一没减够,而V二用的是V一的指针
Dialogue: 0,1:04:30.96,1:04:35.95,Default,,0,0,0,,那V二结构就把V一的指针也一起给释放了
Dialogue: 0,1:04:35.95,1:04:43.04,Default,,0,0,0,,也就是说V一还存在的话,那V指向的就是一个已经释放的指针
Dialogue: 0,1:04:43.04,1:04:51.72,Default,,0,0,0,,这时候这里面的数据可能已经无效,而你还去访问的话,就有可能会被黑客攻击
Dialogue: 0,1:04:51.72,1:05:00.02,Default,,0,0,0,,有怎么样有没有问题,我看看可以看吧
Dialogue: 0,1:05:00.02,1:05:20.44,Default,,0,0,0,,可以的,然后就是所以我所以说前人才说就是不要去用默认的构造函数,我们要么就把它删除掉,就是让用户在这样用的时候,它会生成一个这种错误
Dialogue: 0,1:05:20.44,1:05:27.57,Default,,0,0,0,,就是说哎呀这个拷贝构造函数已经被删除了,你不要再用了
Dialogue: 0,1:05:27.57,1:05:32.41,Default,,0,0,0,,就是如果你不删的话,就会是一个浅拷贝
Dialogue: 0,1:05:32.41,1:05:39.26,Default,,0,0,0,,当然更好的做法就是我们自己去实践一下拷贝构造函数
Dialogue: 0,1:05:39.87,1:05:56.05,Default,,0,0,0,,就像这样,首先我们把error 的size 射进来,然后把other 的data 不对,先要我们自己分配一遍data ,然后再把对方的data 给拷进来
Dialogue: 0,1:05:56.05,1:06:09.35,Default,,0,0,0,,也就是说这个data 是要特殊处理的,就这样的话就会变成一个生拷贝而生拷贝就无惧那个双重福利的问题了
Dialogue: 0,1:06:10.46,1:06:20.37,Default,,0,0,0,,所以说就是说 C++ 你的构造拷贝构造函数始终使用那个呃深拷贝
Dialogue: 0,1:06:20.37,1:06:25.98,Default,,0,0,0,,如果你想用前拷贝的话,待会儿我会讲用智能指针
Dialogue: 0,1:06:25.98,1:06:36.93,Default,,0,0,0,,然后这个其实也是体现了我们刚刚说的分装,也就是比如resides 它其实是把两个操作分装成一个
Dialogue: 0,1:06:36.93,1:06:57.24,Default,,0,0,0,,然后这种拷贝呢也是先拷贝赛在拷贝data ,在初始化data 也是一个分装的思想,也就是保证一个操作的前后就是我一旦一个操作完成,要么不完成,要么完成前后都是对象处于正确状态的
Dialogue: 0,1:06:57.24,1:07:01.97,Default,,0,0,0,,这样就可以避免C语言常见的空指针现象
Dialogue: 0,1:07:04.70,1:07:19.65,Default,,0,0,0,,这个所以说拍送它是不支持那个 C++ 结构的,它返回的只能是POD结构前拷贝是拷贝地址呀
Dialogue: 0,1:07:19.65,1:07:21.82,Default,,0,0,0,,对呀,没有分配内存
Dialogue: 0,1:07:24.85,1:07:37.31,Default,,0,0,0,,所以说如果你有解构函数,一定要么删除,要么自定义默认那个是前拷贝的,知道了吧?
Dialogue: 0,1:07:38.36,1:07:44.89,Default,,0,0,0,,然后为什么为什么他还说还要同时删除拷贝赋值呢?
Dialogue: 0,1:07:44.89,1:07:51.14,Default,,0,0,0,,因为拷贝赋值也是便于其自动生成的一个前拷贝
Dialogue: 0,1:07:51.47,1:07:56.66,Default,,0,0,0,,所以说我们也要制定一下这个拷贝复制函数
Dialogue: 0,1:07:57.68,1:08:05.40,Default,,0,0,0,,但是如果我们这个拷贝的操作很复杂,我不想再重新实现一遍,怎么办?
Dialogue: 0,1:08:05.40,1:08:14.46,Default,,0,0,0,,可以用这个语法,就是我首先把当前对象给解构掉呃,解构掉,再调用拷贝构造函数
Dialogue: 0,1:08:14.46,1:08:22.71,Default,,0,0,0,,当当场在我当前这个对象的头上去构造,用我们placement new 语法就是new victor
Dialogue: 0,1:08:22.71,1:08:40.30,Default,,0,0,0,,不对,我要先指定它在this 这个地址上去新建一个对象,而不是从在呃堆上去分配一个内存去创建,这就是placement new ,它相当于直接在日志上调用了拷贝构造函数
Dialogue: 0,1:08:40.63,1:08:47.36,Default,,0,0,0,,这样的话呢就可以至少保证它数值是正确的
Dialogue: 0,1:08:47.36,1:08:58.50,Default,,0,0,0,,但如果我们要追求性能,看能不能是先free ,然后再重新构造,我们可以直接利用当前的data 去重新分配
Dialogue: 0,1:08:58.50,1:09:14.53,Default,,0,0,0,,也就是如果当前的data 里面本来就有一段内存了,可以用there a lot 来把当前的内存扩大,从而就避免了再去释放,再去分配,这样可能会提高性能
Dialogue: 0,1:09:14.53,1:09:21.06,Default,,0,0,0,,所以说我们可以是有时候是需要自定义一个负值函数的
Dialogue: 0,1:09:22.24,1:09:40.00,Default,,0,0,0,,如果不需要考虑的话,就用这个语法去加一个假的那个就先解构自己,然后再初始化自己,这样也能实现赋值的语义,就是等于这个加这个嘛
Dialogue: 0,1:09:41.67,1:09:47.92,Default,,0,0,0,,所以说这就是为什么定义了拷贝构造,必须同时定义拷贝赋值
Dialogue: 0,1:09:48.45,1:09:56.78,Default,,0,0,0,,然后除了拷贝以外,就是还有一种构造对象的语义是移动语义
Dialogue: 0,1:09:56.78,1:09:59.02,Default,,0,0,0,,为什么要移动呢?
Dialogue: 0,1:09:59.02,1:10:07.51,Default,,0,0,0,,就是移动它是只移动一个指针,就是你们不是说前拷贝和深拷贝吗?
Dialogue: 0,1:10:07.51,1:10:13.89,Default,,0,0,0,,就是拷贝它都是深的,而移动是浅的,为什么不能浅拷贝呢?
Dialogue: 0,1:10:13.89,1:10:19.48,Default,,0,0,0,,因为浅拷贝会导致双重free ,而且移动呢是没问题的
Dialogue: 0,1:10:19.48,1:10:24.26,Default,,0,0,0,,因为移动了之后,另一个东西它就被清零了
Dialogue: 0,1:10:24.26,1:10:41.55,Default,,0,0,0,,就比如我这里V一是1 10的长度,V二是200的长度,V一等于move v 2的话就把V二二百个数的指针移动到V一里,然后同时又把V二的这个指针给清零
Dialogue: 0,1:10:41.55,1:10:45.54,Default,,0,0,0,,这样的话不是还是只有一个对象吗?
Dialogue: 0,1:10:45.54,1:10:50.86,Default,,0,0,0,,就不会有拷贝出前拷贝,造成了这个双重福瑞了
Dialogue: 0,1:10:50.86,1:10:56.18,Default,,0,0,0,,就福瑞的时候V二已经是零了,已经不用福瑞了
Dialogue: 0,1:10:56.18,1:11:04.87,Default,,0,0,0,,而V一的话呢嗯呃V一的话呢它接管了V2的这个内存呢所有权
Dialogue: 0,1:11:04.87,1:11:09.87,Default,,0,0,0,,所以free 的时候只有唯一被free ,就避免了双重free
Dialogue: 0,1:11:10.20,1:11:15.89,Default,,0,0,0,,然后拷贝的话呢,V一和V2是3拷贝指向不同的地址
Dialogue: 0,1:11:15.89,1:11:24.56,Default,,0,0,0,,所以拷贝了以后V2的2百,你的数据跑到了V1 ,但V2的指针和V一还是独立的
Dialogue: 0,1:11:24.56,1:11:34.94,Default,,0,0,0,,就它们结构的时候是结构的两个不同的内存块,也没有那个双重的问题,有问题吗?
Dialogue: 0,1:11:36.60,1:11:47.86,Default,,0,0,0,,然后移动是把一V2移到V1 ,然后还有一个更高级的是STDswipe ,就是把V一和V2交换
Dialogue: 0,1:11:47.86,1:12:03.93,Default,,0,0,0,,它其实就相当于之前就是先把T2移到一个临时数据上,然后T2在再把T一到T2能再把原来保存好的T2再移到T1上
Dialogue: 0,1:12:03.93,1:12:13.74,Default,,0,0,0,,就是C语言经典案例swap 两个数据,在C家家里可以这样写,有问题吗?
Dialogue: 0,1:12:14.87,1:12:26.85,Default,,0,0,0,,然后在我们高性能计算中有这样一个场景,就是乒乓缓存,就是从一里面的数据,就常见于一些仿真的那个环节
Dialogue: 0,1:12:26.85,1:12:45.63,Default,,0,0,0,,就是我根据V一的数据算出V2 ,然后下一步的时候就是从V2算到V1 ,就是可以避免读到自己的招数据,呃,就是可以用STDswap 去做它的交换,复杂度是O一的
Dialogue: 0,1:12:45.63,1:12:50.91,Default,,0,0,0,,然后只有拷贝的话,它会造成ON的复杂度
Dialogue: 0,1:12:50.91,1:12:56.77,Default,,0,0,0,,所以说善用移动和交换可以使你的复杂度变低
Dialogue: 0,1:12:57.23,1:13:12.09,Default,,0,0,0,,比如这样就是V本来是110的,后来是200的话,就是他们两个的内存交换了,就V一变成200 ,V2变成有问题吗?
Dialogue: 0,1:13:12.67,1:13:21.15,Default,,0,0,0,,你原本资源那就变成二去释放了呀,还有问题吗?
Dialogue: 0,1:13:25.27,1:13:32.96,Default,,0,0,0,,哈哈嗯,你们的清晰度可以吗?
Dialogue: 0,1:13:34.50,1:13:49.67,Default,,0,0,0,,可以的,然后就是移动,我们不是说就是默认一个等号是拷贝啊,要移动的话需要ST级目录嘛
Dialogue: 0,1:13:49.67,1:13:54.94,Default,,0,0,0,,但是有的时候是不需要指定ST0目录的
Dialogue: 0,1:13:55.54,1:14:09.32,Default,,0,0,0,,就是比如这些情况,就如果我是一个返回值的话,因为函数都返回了嘛,之后不会再用V二了,就不需要再拷贝一下V2来返回啊
Dialogue: 0,1:14:10.03,1:14:29.47,Default,,0,0,0,,所以 C++ 标准规定,如果你是返回了一个VI的话,这时候VI一定等价于同一个move 的VR,也就是返回值优化返回值始终是移动语义,然后还有一个语义也是移动的
Dialogue: 0,1:14:29.47,1:14:41.53,Default,,0,0,0,,就是如果我不是一个VE的语言,语言是另一个对象,而是一个当场创建了一个victor 对象,这时候称之为就地构造的
Dialogue: 0,1:14:41.53,1:14:47.81,Default,,0,0,0,,也就是说这个别克等我这个语句结束之后,不会再有人用了
Dialogue: 0,1:14:47.81,1:14:51.08,Default,,0,0,0,,那这时候他去调用拷贝干嘛呢?
Dialogue: 0,1:14:51.08,1:14:58.37,Default,,0,0,0,,随便一句就是说这时候也是移动语义,当然显示的移动也会变成移动
Dialogue: 0,1:14:58.37,1:15:05.40,Default,,0,0,0,,就是这两种是虽然我们没有写ST顶部,但他们也是相当于移动的
Dialogue: 0,1:15:05.40,1:15:08.42,Default,,0,0,0,,这是编译器自动做出的优化
Dialogue: 0,1:15:09.28,1:15:25.25,Default,,0,0,0,,然后如果我们希望在返回值调用一次拷贝,可以把T转换为t cos 的和也就是我们那个拷贝构造函数的参数类型,这样才会去调用拷贝
Dialogue: 0,1:15:25.25,1:15:35.78,Default,,0,0,0,,但通常我们只需要移动就行了,以及我们可以就是V直接等于2 ,V二是一个另一个对象
Dialogue: 0,1:15:35.78,1:15:47.10,Default,,0,0,0,,这时候编译器认为哦V2之后还会使用,那我不敢移动,我还是要保留V2的,所以它就默认变成拷贝了
Dialogue: 0,1:15:47.10,1:15:54.21,Default,,0,0,0,,但是你不要以为木屋其实做的任何事情,它只是一个修饰符而已
Dialogue: 0,1:15:54.21,1:16:11.64,Default,,0,0,0,,你如果直接写STDMVR是不会清空VR的STDScos VR也不会拷贝VR你要用auto 任何一个任何一个变量,米等于V2才会让他真正的去拷贝一下
Dialogue: 0,1:16:12.72,1:16:23.93,Default,,0,0,0,,然后如果你要清空一二的话,可以用一二等于括号,这样就调用它的默认构造函数加移动赋值函数
Dialogue: 0,1:16:23.93,1:16:33.51,Default,,0,0,0,,或者如果VR是一个victor 类,可以用它的claim 来把victor 设置为零的大小就可以清空了
Dialogue: 0,1:16:34.76,1:16:43.61,Default,,0,0,0,,他们只是转换类型,实际产生效果的还是唯一的赋值呃,移动赋值函数嘛
Dialogue: 0,1:16:44.96,1:17:04.57,Default,,0,0,0,,然后如果你对降低这个时间复杂度不感兴趣的话,就你可以直接就是啊不不不,就是如果你不定义移动构造函数的话,它会自动去调用拷贝构造函数
Dialogue: 0,1:17:04.57,1:17:12.49,Default,,0,0,0,,就是移动构造,相当于拷贝构造,然后把它解构掉,再把它清0
Dialogue: 0,1:17:13.65,1:17:20.95,Default,,0,0,0,,不对,就是移动构造就相当于我拷贝了它,然后把它清零
Dialogue: 0,1:17:23.64,1:17:30.37,Default,,0,0,0,,如果你不定移动构造的话,它默编译器也会默认这样做的
Dialogue: 0,1:17:30.37,1:17:41.31,Default,,0,0,0,,所以说如果你不想提供一个OE复杂度的移动的话,你直接不声明移动构造函数也是可以的
Dialogue: 0,1:17:41.31,1:17:47.77,Default,,0,0,0,,这就是为什么三无法则说不定移动低效的,但不会出错
Dialogue: 0,1:17:48.13,1:17:56.75,Default,,0,0,0,,所以如果你想要高效的话,还是需要自己定义一下移动构造函数的
Dialogue: 0,1:17:56.75,1:18:05.08,Default,,0,0,0,,然后我们移动呢因为是浅浅移动,所以说不需要就是进行一个mallock
Dialogue: 0,1:18:05.08,1:18:12.21,Default,,0,0,0,,然后memory copy 我们直接把它的大小和那个值移过来就行了
Dialogue: 0,1:18:12.21,1:18:25.60,Default,,0,0,0,,当然移过之后还不要忘了把他的对象给清零,就是把他的这个尺寸设为零,这样的话呢才能避免double 的问题
Dialogue: 0,1:18:26.81,1:18:39.10,Default,,0,0,0,,差不多吧,总之就是他移动了之后只有一个对象,所以可以用浅移动,所以才能达到OE的
Dialogue: 0,1:18:39.10,1:18:44.32,Default,,0,0,0,,然后提高性能的话还是有一个移动复制函数
Dialogue: 0,1:18:44.32,1:18:55.06,Default,,0,0,0,,我们如果不感兴趣的话,也可以用之前的imprisonment new 去先解构,然后再调用这个移动构造函数
Dialogue: 0,1:18:56.20,1:19:23.73,Default,,0,0,0,,这个刚刚说过了,就是如果我删除的他们的就是如果我如果我不想那个自定义一个一个呃,不是不是自定义一个那个拷贝复制函数的话,我可以删掉它,然后直接只实现移动赋值函数就可以了
Dialogue: 0,1:19:23.73,1:19:25.55,Default,,0,0,0,,这是为什么呢?
Dialogue: 0,1:19:25.55,1:19:35.56,Default,,0,0,0,,因为这个移动复制函数参数类型是victor,而这个victor 可以被从这个应用中构造
Dialogue: 0,1:19:35.56,1:19:51.33,Default,,0,0,0,,所以如果我写这个,而这个被删除的话,他就会认为哦,你是想要先把这个转换为这个,然后再去调用这个及时构造的那个对象
Dialogue: 0,1:19:51.33,1:20:04.37,Default,,0,0,0,,就是他会这么认为,从而认为你的右边是一个就地构造对象,从而触发移动语义,从而使移动不知函数
Dialogue: 0,1:20:04.37,1:20:09.41,Default,,0,0,0,,然后所以是可以安全的删除他
Dialogue: 0,1:20:09.41,1:20:19.06,Default,,0,0,0,,那当然如果你把拷贝构造函数声明为explanation 的话,那这个方法就不行了
Dialogue: 0,1:20:19.06,1:20:22.35,Default,,0,0,0,,还是要P二等于left v 一才行
Dialogue: 0,1:20:26.55,1:20:37.80,Default,,0,0,0,,然后总结一下,就是有这几种会调用什么函数,大家可以记一下有什么问题吗?
Dialogue: 0,1:20:39.88,1:20:41.74,Default,,0,0,0,,有问题吗?
Dialogue: 0,1:20:43.48,1:20:44.76,Default,,0,0,0,,没有问题
Dialogue: 0,1:20:50.31,1:20:52.53,Default,,0,0,0,,已经晕了吗?
Dialogue: 0,1:20:56.37,1:21:14.36,Default,,0,0,0,,不要啊,总之这个是移动,它是就地构造,所以是移动,然后返回,因为它是有编译器优化,所以也会变成移动
Dialogue: 0,1:21:14.36,1:21:23.63,Default,,0,0,0,,然后这个指明了move 也会变成移动,然后直接写等号的话是拷贝就是这些规则
Dialogue: 0,1:21:25.51,1:21:31.08,Default,,0,0,0,,然后构造函数你已经彻底学废了
Dialogue: 0,1:21:31.41,1:21:39.40,Default,,0,0,0,,所以说我们学会了构造函数以后,就可以开始理解智能指针了
Dialogue: 0,1:21:40.22,1:21:52.58,Default,,0,0,0,,就首先就是我们还是回到C1198 ,我们那时候还在普遍的用new 和delete 来管理内存
Dialogue: 0,1:21:52.92,1:21:56.89,Default,,0,0,0,,但是这有一个什么问题呢?
Dialogue: 0,1:21:56.89,1:21:59.58,Default,,0,0,0,,就是还是my lock free 的问题
Dialogue: 0,1:21:59.58,1:22:07.12,Default,,0,0,0,,就是如果我溜了,但是忘记去点练它了,就是甚至我可能有多个分支
Dialogue: 0,1:22:07.12,1:22:15.73,Default,,0,0,0,,而如果我命令函数,哎呀,我记得点亮它,但我不小心在某个分支里忘记点亮它
Dialogue: 0,1:22:16.45,1:22:23.71,Default,,0,0,0,,那这时候如果出了这个小状况的话,这个拼音就不会被释放了
Dialogue: 0,1:22:23.71,1:22:30.70,Default,,0,0,0,,你看分配内存出了点小状况,然后忘记释放内存了,就很危险
Dialogue: 0,1:22:32.17,1:22:41.77,Default,,0,0,0,,所以说这个问题不就是我们刚刚IAI视角所想要解决的问题吗?
Dialogue: 0,1:22:41.77,1:22:50.34,Default,,0,0,0,,也就是我一旦分配了指针,我想要让它在结构函数里自动删除,有没有这个类呢?
Dialogue: 0,1:22:50.34,1:23:05.09,Default,,0,0,0,,这个类就是我们 C++ 11期出的unique point ,它的功能就是它可以新建一个对象之后,然后在任何一个返回语句之前自动被放
Dialogue: 0,1:23:05.09,1:23:12.11,Default,,0,0,0,,它是通过结构函数来实现这一年的,这个基本上没区别
Dialogue: 0,1:23:12.11,1:23:22.15,Default,,0,0,0,,唯一的区别就是如果C是int 这一个会触发它的随机初始化,而这个能够保证是零初始化的
Dialogue: 0,1:23:22.15,1:23:49.68,Default,,0,0,0,,就只有这一点区别,别的没区别,这两个基本是一样的,除了对于POD类型以外,嗯,然后我们这里有一个unique point 容器,它的结构函数里会自动delete p 然后make unique 呢就相当于我们原来的6C括号
Dialogue: 0,1:23:49.68,1:24:00.90,Default,,0,0,0,,然后括号里可以有参数,也可以没有,我们这里是没有,所以就是unique point
Dialogue: 0,1:24:00.90,1:24:05.18,Default,,0,0,0,,它还有一点智能,就是体现在分装
Dialogue: 0,1:24:05.18,1:24:19.22,Default,,0,0,0,,就是以前我们在酒吧时代的CTR家里,经常有这种说法,就是给列成一个指针之后,务必把这个指针设为no ,为什么呢?
Dialogue: 0,1:24:19.22,1:24:37.85,Default,,0,0,0,,就是为了防止就是我已经点亮它了之后,又有人一不小心使用了这个,就可能会造成指向一个不存在的地址,从而使空悬指针,从而有可能被黑客利用
Dialogue: 0,1:24:37.85,1:24:49.05,Default,,0,0,0,,所以说unique point 它很智能,它的检测到啊我被复制为一个空指针了,那它就会自动去delete 它
Dialogue: 0,1:24:49.05,1:24:56.15,Default,,0,0,0,,当前所持有的那个指针,所以这也是体现了一个分装不变性的思想
Dialogue: 0,1:24:56.15,1:25:11.86,Default,,0,0,0,,就是我任何一个操作都是原子弹,要么做,要么不做,做之前和做之前做呃,不是做之前和做之后,这个对象都是处于正确的状态,不会出现也指针的情况
Dialogue: 0,1:25:11.86,1:25:26.86,Default,,0,0,0,,哦,当然这个P等于no point ,它也有一个成员函数叫P点reset ,它的含义是一样的啊,有什么问题吗?
Dialogue: 0,1:25:30.15,1:25:34.07,Default,,0,0,0,,什么有人吗?
Dialogue: 0,1:25:35.33,1:25:36.96,Default,,0,0,0,,嘿有人
Dialogue: 0,1:25:39.14,1:26:01.11,Default,,0,0,0,,然后就是可以看到我们这个分配内存,然后我们提前释放释放成功,可以看到释放内存是卡在这个地方的,就体现了它是在这个地方进行了一次代练的,而这个呢则是在他最后离开的一个return 语句进行一个释放
Dialogue: 0,1:26:01.11,1:26:18.88,Default,,0,0,0,,然后我们这是提前释放,然后unique pointer 它有一个被新人认为是很烦的特性,就是它是删除了拷贝构造函数了
Dialogue: 0,1:26:18.88,1:26:29.74,Default,,0,0,0,,然后有的就会说,哎呀,你看小鹏老师,我这个批为什么不能作为放款的参数啊?
Dialogue: 0,1:26:29.74,1:26:36.79,Default,,0,0,0,,就是因为这是很硬核,就是因为unique point 不能被拷贝
Dialogue: 0,1:26:36.79,1:26:44.24,Default,,0,0,0,,如果你是这样的话,他其实会触发一次拷贝的,那怎么办呢?
Dialogue: 0,1:26:44.24,1:26:50.47,Default,,0,0,0,,别担心,就是啊不是不是,就是说为什么他不让拷贝呢?
Dialogue: 0,1:26:50.47,1:26:52.74,Default,,0,0,0,,当然还是三无法则
Dialogue: 0,1:26:52.74,1:27:04.06,Default,,0,0,0,,因为unique point 自定义的结构函数为delete ,所以说它必须得删除拷贝函数,否则拷贝就是一个浅拷贝
Dialogue: 0,1:27:04.06,1:27:13.97,Default,,0,0,0,,而浅拷贝它会造成重复释放,所以说它宁可变性出错,也不要在运行时出错,它是对的
Dialogue: 0,1:27:13.97,1:27:30.96,Default,,0,0,0,,你好,不是为了刁难你哦,所以如果你想要解决它的这个刁难性,你可以要么用这个方法,也就是通过gap 获取出指针,然后你把这个指针去做什么事
Dialogue: 0,1:27:30.96,1:27:34.36,Default,,0,0,0,,没关系,但这是分两种情况的
Dialogue: 0,1:27:34.36,1:27:40.31,Default,,0,0,0,,第一种情况就是你的饭卡只是这批做了一些事情
Dialogue: 0,1:27:42.48,1:27:55.17,Default,,0,0,0,,西安的point 是原子弹,然后就是你只是对他做了一些事情,你并不是想要这个这个对象的控制权呀
Dialogue: 0,1:27:55.17,1:28:01.34,Default,,0,0,0,,这时候直接从P你get 出一个原始的乘号指针就可以了
Dialogue: 0,1:28:01.34,1:28:13.15,Default,,0,0,0,,然后你对着这个指针做什么事情,但你其实并没有修改它什么时候释放这件事,这时候就可以传原始指针
Dialogue: 0,1:28:13.15,1:28:21.74,Default,,0,0,0,,如果你需要就是把这个对象的生命周期交给份卡,那就得用移动构造函数吧
Dialogue: 0,1:28:21.74,1:28:26.04,Default,,0,0,0,,unique pond 它是禁止拷贝,但它可以移动呀
Dialogue: 0,1:28:26.04,1:28:38.12,Default,,0,0,0,,就是比如我这里有一个OBJlist ,我的的功能是想要把你新建的这个对象添加到全局的一个对象列表里面
Dialogue: 0,1:28:39.15,1:28:53.15,Default,,0,0,0,,就是说我是想要比如这个名字改成old open jacket ,那这时候你可能需要的是把份额继续上面为unique 类型
Dialogue: 0,1:28:53.15,1:29:03.68,Default,,0,0,0,,然后这里采用那个移动构造函数去构造,就可以让它就移交了控制权,从而避免多重拷贝
Dialogue: 0,1:29:03.68,1:29:11.28,Default,,0,0,0,,就比如我移交前,这个unique point 是不为空的,它里面是指向对象的
Dialogue: 0,1:29:11.28,1:29:20.98,Default,,0,0,0,,但是移动构造函数之后,它就会把P移交给funk ,然后funk 又进一步移交到这个OBGlist 里
Dialogue: 0,1:29:20.98,1:29:32.56,Default,,0,0,0,,这时候外面的P就会变成空,因为移交移动嘛,它要避免创建两个前拷贝,它会把原来的那个对象设为空
Dialogue: 0,1:29:32.56,1:29:46.57,Default,,0,0,0,,你就比如说你看这里,我移交前是一个有地址的值,移交之后它就会清空这个指针,然后释放内存的时候,它就不用重复释放了
Dialogue: 0,1:29:46.57,1:29:59.38,Default,,0,0,0,,就只有欧米茄list 被删除的时候,也就是退出的时候,他才会被才会被那个那个C语言给删除了,明白了吧?
Dialogue: 0,1:30:00.03,1:30:05.46,Default,,0,0,0,,所以要分两个情况啊,小鹏老师为什么这里出错了?
Dialogue: 0,1:30:05.46,1:30:07.79,Default,,0,0,0,,别着急,要分两个情况
Dialogue: 0,1:30:07.79,1:30:17.89,Default,,0,0,0,,第一种情况是你只是想要对P进行一些操作,而不想要它的生命周期,那你就可以用原始指针
Dialogue: 0,1:30:17.89,1:30:32.65,Default,,0,0,0,,如果你需要它的生命周期呢,比如把这个对象加到某个全局的对象表里,这时候你就需要移交通过STDmove 才能就是把控制权移交给他
Dialogue: 0,1:30:32.65,1:30:44.29,Default,,0,0,0,,但是我们发现这移交有个什么问题啊,就是一旦移交了之后,我就再也不能访问到原来的这个地址了
Dialogue: 0,1:30:44.29,1:30:46.14,Default,,0,0,0,,因为它变成闹了
Dialogue: 0,1:30:46.14,1:30:55.03,Default,,0,0,0,,就比如这个情况,就我先是移交了,然后再对这个P做什么事情,这时候就会出错
Dialogue: 0,1:30:55.03,1:30:58.42,Default,,0,0,0,,因为移交之后P就变成空指针了
Dialogue: 0,1:30:58.75,1:31:02.99,Default,,0,0,0,,如果我们还想访问到的话,要怎么办呢?
Dialogue: 0,1:31:02.99,1:31:04.85,Default,,0,0,0,,可以用这个方法
Dialogue: 0,1:31:04.85,1:31:20.78,Default,,0,0,0,,首先我们是可以提前获取原始指针的,就是趁它还没移走之前,我先把它get 出来,然后再对着这个get 出来的原始指针做什么事情就没问题了,对吧?
Dialogue: 0,1:31:20.78,1:31:25.29,Default,,0,0,0,,就可以就可以让它保留原来指向的地方
Dialogue: 0,1:31:25.29,1:31:36.07,Default,,0,0,0,,但是这有一个前提条件,就是你这时候不能把他更可移交过去的生命对象给结束掉
Dialogue: 0,1:31:36.07,1:31:42.08,Default,,0,0,0,,就比如我这个给他了,然后又把这个欧米茄list 给清掉了
Dialogue: 0,1:31:42.08,1:31:51.75,Default,,0,0,0,,这时候若批就会变成一个空悬指针,也就是我这里已经删除了,你还在去调用呢,就很危险
Dialogue: 0,1:31:51.75,1:32:00.11,Default,,0,0,0,,所以这种用法仅限于就是你知道这个think 之后它还是存在的,不会立马被删除
Dialogue: 0,1:32:00.11,1:32:01.42,Default,,0,0,0,,那你可以用
Dialogue: 0,1:32:01.42,1:32:09.00,Default,,0,0,0,,如果你知道funk ,比如欧米茄lessons clear 了,就把原来这个智能指针给删除了
Dialogue: 0,1:32:09.71,1:32:15.55,Default,,0,0,0,,就是比如这样就是分配内存,就是这个地方我的数字是12
Dialogue: 0,1:32:15.55,1:32:21.17,Default,,0,0,0,,然后这个是在这个地方,然后释放内存这个对应的这一行
Dialogue: 0,1:32:21.17,1:32:30.99,Default,,0,0,0,,然后我的数字是这这这什么乱七八糟,这是因为OBGlist 释放了,导致这个P所指向的对象也释放了
Dialogue: 0,1:32:30.99,1:32:39.42,Default,,0,0,0,,所以这时候你去访问到的就是一个空闲指针里面,是一些乱七八糟的数据,甚至会崩溃
Dialogue: 0,1:32:40.06,1:32:46.35,Default,,0,0,0,,对对对,所以要解决这种问题,就是解决空悬指针的问题
Dialogue: 0,1:32:46.35,1:32:48.82,Default,,0,0,0,,就有一个无敌的方案
Dialogue: 0,1:32:48.82,1:32:58.13,Default,,0,0,0,,基本无敌的方案就是智能指针,也就是智能指针,它解决了unique point 不能拷贝的问题
Dialogue: 0,1:32:58.13,1:32:59.77,Default,,0,0,0,,它怎么解决的?
Dialogue: 0,1:32:59.77,1:33:05.44,Default,,0,0,0,,它是通过引用技术,为什么unique point 不让拷贝呢?
Dialogue: 0,1:33:05.44,1:33:12.20,Default,,0,0,0,,这是因为它就是如果拷贝了,那就有两个指针指向同一个对象
Dialogue: 0,1:33:12.20,1:33:16.88,Default,,0,0,0,,而这两个指针被解构的时候,它就会删两遍
Dialogue: 0,1:33:16.88,1:33:25.19,Default,,0,0,0,,而shell the point 它比较智能,它会在它指向的那个对象前面加一个int 类型的atomic
Dialogue: 0,1:33:25.19,1:33:32.73,Default,,0,0,0,,然后当这个share point 被拷贝一次的时候,它前面这个引用技术就会加1
Dialogue: 0,1:33:32.73,1:33:38.96,Default,,0,0,0,,然后如果需要的话呢,被删掉一个,那这引用技术就会减1
Dialogue: 0,1:33:38.96,1:33:47.02,Default,,0,0,0,,当如果所有的share point 被减全部被解构的话,那这个引用技术不是归零了吗?
Dialogue: 0,1:33:47.02,1:33:54.56,Default,,0,0,0,,他这时候才会去删除,从而避免就是结构一次就删除,导致重复的删除
Dialogue: 0,1:33:55.42,1:34:01.99,Default,,0,0,0,,所以西安的panda 它可以实现安全的前拷贝
Dialogue: 0,1:34:01.99,1:34:07.92,Default,,0,0,0,,对,但是但是不要以为写的pattern 就是万能的了
Dialogue: 0,1:34:07.92,1:34:12.88,Default,,0,0,0,,那是不是unique point 和原始指针就不需要了呢?
Dialogue: 0,1:34:12.88,1:34:20.05,Default,,0,0,0,,不一定,它有效率上的优势,也就是说它需要维护一个原子的
Dialogue: 0,1:34:20.05,1:34:27.22,Default,,0,0,0,,就是如果我从多个线程去拷贝这个线的框架,它也能保证安全
Dialogue: 0,1:34:27.55,1:34:37.69,Default,,0,0,0,,但是他这样的话就得用一些硬件的指令来保证它的原子,从而它的效率就没有unique point 高
Dialogue: 0,1:34:43.19,1:34:49.95,Default,,0,0,0,,然后unique pointer 啊,不是不是他还有一个成员函数叫点优质抗的
Dialogue: 0,1:34:49.95,1:34:58.53,Default,,0,0,0,,这就是我们刚才提到的引用技术,我们可以用P点优质抗能获取它的引用技术
Dialogue: 0,1:34:59.23,1:35:11.77,Default,,0,0,0,,就是我们可以看就是刚才这里不是这样嘛,我们看这就是先创建一个对象,这时候引用技术是初始化为一了
Dialogue: 0,1:35:11.77,1:35:19.13,Default,,0,0,0,,然后这里我们拷贝给funk 一次,这时候这个引用技术就变成二了
Dialogue: 0,1:35:19.13,1:35:26.23,Default,,0,0,0,,因为funk 也持有一个引用技术,然后再来一次,这时候就会变成3
Dialogue: 0,1:35:26.56,1:35:36.48,Default,,0,0,0,,然后我们对着这个P做一些什么事情,这个没关系,因为它不是移动,而是拷贝,所以P的值仍然没有变
Dialogue: 0,1:35:36.48,1:35:39.56,Default,,0,0,0,,所以我们还可以对它使用这个
Dialogue: 0,1:35:42.49,1:35:53.47,Default,,0,0,0,,然后就是我们现在把欧米茄list clear 了,也就是把刚才两个移交给啊不拷贝给phone 的那个指针给释放掉了
Dialogue: 0,1:35:53.47,1:35:57.13,Default,,0,0,0,,这时候只剩下我们这一个引用了
Dialogue: 0,1:35:57.13,1:36:03.40,Default,,0,0,0,,所以这时候优质看的是一,这时候我们还是可以做一些事
Dialogue: 0,1:36:03.40,1:36:12.29,Default,,0,0,0,,因为引用技术还剩一嘛不会被释放,只有大约探灵这个地方P才是被彻底销毁了
Dialogue: 0,1:36:12.29,1:36:25.11,Default,,0,0,0,,这时候P指向的对象就变成了引用激素零了,这时候才会被释放,这就不会出现之前原始指针这个提前释放的问题呢
Dialogue: 0,1:36:25.44,1:36:40.18,Default,,0,0,0,,那要是技术变为零了,技术变为零,你还不想让他消失,你都没有人用这个指针,你还不让他消失,想干嘛可以呀?
Dialogue: 0,1:36:40.18,1:36:51.06,Default,,0,0,0,,你只要把这个引用技这个指针存到一个全局变量里,它就永远不会消失,直到程序退出,它才会消失
Dialogue: 0,1:36:51.06,1:36:52.13,Default,,0,0,0,,知道了吧?
Dialogue: 0,1:36:54.48,1:37:00.26,Default,,0,0,0,,然后西安的pointer ,你可能认为哎是很方便呀
Dialogue: 0,1:37:00.26,1:37:21.17,Default,,0,0,0,,如果我不在乎性能是不是可以一直使用shell point ,不只有一个point ,不要用nick point 呢,想的美不只有性能,一个地方不太好,他还有一个地他有可能会产生循环引用
Dialogue: 0,1:37:21.99,1:37:23.38,Default,,0,0,0,,怎么说呢?
Dialogue: 0,1:37:23.38,1:37:36.53,Default,,0,0,0,,就是就是这个就是我有一个C类型,然后它有包含它的那个负类子啊,不是什么负类负对象子啊
Dialogue: 0,1:37:36.53,1:37:49.18,Default,,0,0,0,,就我拿那个公益举例,就假如C是一个窗口类,这个parent 的指向的是它的副窗口,然后确认的是指向他的子窗口
Dialogue: 0,1:37:49.18,1:37:59.62,Default,,0,0,0,,然后我们的parent 说我有一个孩子是这个child ,然后child 又说我有一个副类啊,不是副窗口叫parent
Dialogue: 0,1:37:59.62,1:38:07.32,Default,,0,0,0,,然后我们同时把parent 和chair 释放掉,完了他们都没有被释放,为什么呢?
Dialogue: 0,1:38:07.32,1:38:24.64,Default,,0,0,0,,因为chair 里面还有一个引用指向parent 呢,parent 里也有一个引用指向child 呢,所以说pilot 和chat 相互引用,他们互相引用,就保证他们的应用技术还是以就没有被释放
Dialogue: 0,1:38:24.64,1:38:39.21,Default,,0,0,0,,谁知道这里他们都没有被释放,直到命函数退出,他都没有被释放,就会导致这两块内存永远得不到释放,这是很常见的一个循环引用问题
Dialogue: 0,1:38:39.21,1:38:44.29,Default,,0,0,0,,在C语言中,他们有特定的算法来解决循环引用
Dialogue: 0,1:38:44.29,1:38:51.65,Default,,0,0,0,,而我们C语言的呃不是 C++ 语言的share point ,是解决不了循环引用的
Dialogue: 0,1:38:51.65,1:39:00.23,Default,,0,0,0,,要解决循环引用,我们需要自己手动的把其中一个需要的朋友给改成weak point
Dialogue: 0,1:39:00.23,1:39:02.62,Default,,0,0,0,,one point 是什么意思呢?
Dialogue: 0,1:39:02.62,1:39:15.16,Default,,0,0,0,,就是说我们的shell pointer 刚才不是说因为我还是指向了腹内啊不付窗口,所以说赴窗口的引用还是以
Dialogue: 0,1:39:15.90,1:39:24.82,Default,,0,0,0,,但我们通常的情况是,希望让副窗口被释放的时候,这个孩子也会被释放,对吧?
Dialogue: 0,1:39:25.30,1:39:33.49,Default,,0,0,0,,那我们就可以让孩子指向指向这个付窗口的这个指针为一个弱指针
Dialogue: 0,1:39:33.49,1:39:44.55,Default,,0,0,0,,弱指针它是不会修改对赴赴赴窗口的这个引用技术呢,对对对对对对,你做了我的作业是吗?
Dialogue: 0,1:39:44.55,1:39:57.47,Default,,0,0,0,,这都被你发现了,就是让我孩子指向负的这个指针为弱指针,也就是孩子的释放与否是不影响腹内的这个引用技术的
Dialogue: 0,1:39:57.47,1:40:01.43,Default,,0,0,0,,这样的话呢相互引用也不会有问题
Dialogue: 0,1:40:01.43,1:40:11.71,Default,,0,0,0,,因为parents 释放了之后,它parent 的这个不影响激素呀,它已经变为零了,所以parent 会不会释放叉呢?
Dialogue: 0,1:40:11.71,1:40:15.67,Default,,0,0,0,,也会被释放,就不会出现刚刚的问题
Dialogue: 0,1:40:17.16,1:40:19.75,Default,,0,0,0,,然后log point 要怎么用呢?
Dialogue: 0,1:40:19.75,1:40:36.16,Default,,0,0,0,,就是首先我们的P初始化为一,然后我们创建一个弱引用之后,它的计数器还是唯一,你看还是唯一就是weak point ,它是不影响它这个计数器的
Dialogue: 0,1:40:36.16,1:40:47.96,Default,,0,0,0,,然后我们把控制权移动给放开了,这首批当然还是唯一啊,因为奉可持有了这个这个P的所有权嘛
Dialogue: 0,1:40:47.96,1:40:57.76,Default,,0,0,0,,所以说这时候VKP是没有仓没有失效的,可以通过x pad 来判断wake p 有没有失效
Dialogue: 0,1:40:59.08,1:41:03.19,Default,,0,0,0,,然后可以看到我们第一次是没有失效
Dialogue: 0,1:41:03.19,1:41:18.90,Default,,0,0,0,,然后我们可以通过wake p 点lock ,让这个lock 返回一个share point ,就是让他再加一个给我们一个指针,然后去做一些事情,这当然是能够正确执行的
Dialogue: 0,1:41:18.90,1:41:24.36,Default,,0,0,0,,因为我们饭盒里还把它存到OBJlist ,有一个引用呢
Dialogue: 0,1:41:24.36,1:41:39.74,Default,,0,0,0,,当然我们现在再把OBJlist 给清空了,这时候再去看V和P因V和P不影响计数器,它的时候share point 的计数器已经归零了,所以这时候就会出现错误
Dialogue: 0,1:41:39.74,1:41:44.70,Default,,0,0,0,,若引用已失效,就是因为72的pata的指针变零了
Dialogue: 0,1:41:44.70,1:42:05.07,Default,,0,0,0,,然后我们的V和P因为不影响引用的那个计数器,所以这个时候VKP就是失效的状态,然后他就能够安全的打印出错误已失效,而不会去执行我们实际获取这个short point 的那个那个事情
Dialogue: 0,1:42:11.12,1:42:15.33,Default,,0,0,0,,对,这样就不会出现野指针问题了
Dialogue: 0,1:42:17.24,1:42:28.12,Default,,0,0,0,,所以说we can point 是非常安全,它能够保证不出现循环引用,同时又不像unique point 和这个原始指针
Dialogue: 0,1:42:28.12,1:42:39.81,Default,,0,0,0,,可能这里有一个方向已经释放了,而这原始指针还指着那呢,就他是不知道unique point 已经被释放了
Dialogue: 0,1:42:39.81,1:42:46.23,Default,,0,0,0,,而weak point 他就知道可以通过expand 来查询对方是否已释放
Dialogue: 0,1:42:46.23,1:42:52.00,Default,,0,0,0,,如果已释放,我就不要再去索有问题吗?
Dialogue: 0,1:42:55.98,1:42:58.87,Default,,0,0,0,,没问题吧,那我继续了
Dialogue: 0,1:43:00.53,1:43:06.95,Default,,0,0,0,,然后智能指针它还可以作为类的成员变量
Dialogue: 0,1:43:06.95,1:43:20.00,Default,,0,0,0,,但有一个事情要注意,就是如果你的那里面有智能真的话,那你可能这个类就变成一个浅拷贝的类
Dialogue: 0,1:43:20.44,1:43:32.39,Default,,0,0,0,,就是要么你的这个类里面有unique point ,因为unique point 它是禁止拷贝的,所以你这个类也会变成禁止拷贝的
Dialogue: 0,1:43:33.58,1:43:40.64,Default,,0,0,0,,就是呃他是会导致卡妹妹删除,但移动还是有的
Dialogue: 0,1:43:40.64,1:43:46.18,Default,,0,0,0,,然后什么时候用,有neighborhood ,什么时候用呢?
Dialogue: 0,1:43:46.18,1:44:07.01,Default,,0,0,0,,就是当这个对象仅仅属于我时,比如窗口可以指向子窗口,那这个就是副窗口,拥有子窗口,所以副窗口指向子窗口的指针是可以为unique patent ,而原始指针有一个什么问题呢?
Dialogue: 0,1:44:07.01,1:44:11.48,Default,,0,0,0,,不是原始指针,怎么什么时候应该用呢?
Dialogue: 0,1:44:11.48,1:44:17.80,Default,,0,0,0,,就是紧当这个对象不属于我,但他一旦释放,我必然被释放
Dialogue: 0,1:44:17.80,1:44:23.85,Default,,0,0,0,,就是比如副窗口被关掉了,那子窗口肯定也会被关掉嘛
Dialogue: 0,1:44:23.85,1:44:29.38,Default,,0,0,0,,所以这时候子窗口指向副窗口,就可以用原始指针
Dialogue: 0,1:44:29.38,1:44:34.91,Default,,0,0,0,,但是你得保证保证副窗口关了,子窗口一定会被关
Dialogue: 0,1:44:34.91,1:44:45.70,Default,,0,0,0,,如果你副窗口关,而子窗口没关的话,这时候子窗口指向副窗口,这个指针就是一个野指针,就很危险
Dialogue: 0,1:44:45.70,1:44:52.81,Default,,0,0,0,,所以为了避免这样的危险,其实也可以使用shadow point 和weak point 的组合
Dialogue: 0,1:44:52.81,1:44:56.23,Default,,0,0,0,,weak point 能提供试驾检测,它更安全
Dialogue: 0,1:44:56.23,1:45:04.98,Default,,0,0,0,,即便你的确是仅仅属于我司,你仍可以使用shell point 和weak point 和因为他们更安全
Dialogue: 0,1:45:04.98,1:45:15.37,Default,,0,0,0,,虽然他们更低效,对对wake 跟share 一起用原始指针跟unique 一起用
Dialogue: 0,1:45:15.37,1:45:19.08,Default,,0,0,0,,这两个是一对这两个是一对
Dialogue: 0,1:45:19.08,1:45:29.43,Default,,0,0,0,,因为wake pointer 它只能用线的,而unique 是不能生成一个way 的
Dialogue: 0,1:45:29.77,1:45:38.53,Default,,0,0,0,,尤尼克不能生成一个维克,尤尼克只能生成一个原始指针,而原始指是没有失效检测的
Dialogue: 0,1:45:40.21,1:45:54.43,Default,,0,0,0,,然后共享的指针它它是能够共享所有权,就是或者就是说你想要用失效检测的weaker point ,那也得用共享
Dialogue: 0,1:45:54.91,1:46:09.08,Default,,0,0,0,,就比如指向窗口中上一次被点击过的,但是你碰巧这个点击的元素,这个窗口还在,而这个元素被删了,那这时候不失效了吗?
Dialogue: 0,1:46:09.08,1:46:16.12,Default,,0,0,0,,这时候就得用微克指针,就是它指向这里,但这个指针是已经失效的
Dialogue: 0,1:46:16.12,1:46:27.90,Default,,0,0,0,,你通过x pile 的判断,就是说啊我上一次点击的元素已经没了,所以说就比原始指针更安全,还有问题吗?
Dialogue: 0,1:46:29.22,1:46:30.49,Default,,0,0,0,,没了
Dialogue: 0,1:46:31.54,1:46:39.03,Default,,0,0,0,,建议初学者多用shell pattern 和weak pattern ,而不是用unique pattern
Dialogue: 0,1:46:39.03,1:46:52.14,Default,,0,0,0,,一方面有neighborhood 禁止,他们就觉得很难用,然后原始指针又不能提供私下检测,这两个可能是更安全
Dialogue: 0,1:46:52.14,1:47:06.37,Default,,0,0,0,,但是它是嗯然后是不是啊这刚才说过的,然后还有一个解决方案,就是直接把第二个设置为一个一个原始指针
Dialogue: 0,1:47:06.37,1:47:20.97,Default,,0,0,0,,但是原始指针注意它是有一个那个危险性,就是有可能赴窗口被删除了,而子窗口还在这时候,这个原始指针就是空悬指针了
Dialogue: 0,1:47:21.85,1:47:33.00,Default,,0,0,0,,所以说要么我们用shadow 和weak ,要么就unique 和这个新号,就是保证这个china 没有再有副本了
Dialogue: 0,1:47:33.00,1:47:40.11,Default,,0,0,0,,这时候用主要是人就会比较安全,充充电口
Dialogue: 0,1:47:44.58,1:48:03.68,Default,,0,0,0,,还有个猫,嗯,当然这个有那个point ,你就是要记住什么地方应该用move ,就是他是不能拷贝,所以要用木语
Dialogue: 0,1:48:05.72,1:48:15.88,Default,,0,0,0,,然后智能指针不是解决了这个没这一项都深拷贝,没办法前拷贝的问题嘛
Dialogue: 0,1:48:15.88,1:48:22.87,Default,,0,0,0,,所以说就是有的对象,就比如窗口这种,它是不需要拷贝的
Dialogue: 0,1:48:23.48,1:48:27.94,Default,,0,0,0,,他想要拷贝他想要的其实是前拷贝
Dialogue: 0,1:48:27.94,1:48:41.92,Default,,0,0,0,,这时候我们就可以把窗口内全部给禁用掉,他们的那个拷贝构造函数,然后统一用share pont 监控号窗口来管理他们
Dialogue: 0,1:48:41.92,1:48:50.25,Default,,0,0,0,,这样就可以把比较麻烦的声拷贝语音给转换成智能指针前拷贝了
Dialogue: 0,1:48:51.24,1:49:06.30,Default,,0,0,0,,就是跟你说一件事,就是 C++ 中所有的对象都是深拷贝,只有shared pointer 是前拷贝,就只有仙人punta 跟weight punta 是千个拷贝
Dialogue: 0,1:49:06.30,1:49:12.25,Default,,0,0,0,,然后unique point 则是直接禁止了,就是这样
Dialogue: 0,1:49:13.96,1:49:18.27,Default,,0,0,0,,然后我们刚才不是提到3无法则吗?
Dialogue: 0,1:49:18.27,1:49:23.44,Default,,0,0,0,,有人说这个已经看晕了,没关系,我也看晕了
Dialogue: 0,1:49:23.44,1:49:34.65,Default,,0,0,0,,就是其实很多时候我们是不需要担心三无法上的,因为都有那个STL容器帮我们包装好了
Dialogue: 0,1:49:34.65,1:49:44.70,Default,,0,0,0,,就是比如STDvictor 在他内部已经去伺候了三无法则,我们就不需要自己再伺候了
Dialogue: 0,1:49:44.70,1:49:51.60,Default,,0,0,0,,就如果你的一个类,它里面包含的是victor it ,而不是it 乘error
Dialogue: 0,1:49:51.60,1:49:58.79,Default,,0,0,0,,这时候你就不需要去担心三无法的,你直接就什么都不需要
Dialogue: 0,1:49:59.12,1:50:05.84,Default,,0,0,0,,他在拷贝的时候能够自动调用victor 升,拷贝就不会出错
Dialogue: 0,1:50:08.04,1:50:16.58,Default,,0,0,0,,当然如果你用的智能指针,它会变成一个浅拷贝的语义,但它也不会出错
Dialogue: 0,1:50:16.58,1:50:25.41,Default,,0,0,0,,当然原始指针其实也可以,但它的前提是从unique point 里get 出来的一个弱引用
Dialogue: 0,1:50:25.41,1:50:29.11,Default,,0,0,0,,它以这个形式存在才是合理的
Dialogue: 0,1:50:29.11,1:50:39.65,Default,,0,0,0,,但其他情况下,就如果是通过我们lock of free 以及new delete 去分配的原始指针,那就是不安全的
Dialogue: 0,1:50:39.65,1:50:45.35,Default,,0,0,0,,它需要你自己去,要么去删除拷贝,要么定义拷贝
Dialogue: 0,1:50:48.27,1:50:55.60,Default,,0,0,0,,然后还有一个虽然是基础类型硬盘,但它对应着某种资源
Dialogue: 0,1:50:55.60,1:50:57.73,Default,,0,0,0,,为什么叫资源呢?
Dialogue: 0,1:50:57.73,1:51:10.49,Default,,0,0,0,,就比如是就比如open GO可以通过GOcreate text 来创建一个管理,然后通过jail delete text 来删除一个纹理
Dialogue: 0,1:51:10.49,1:51:25.77,Default,,0,0,0,,这种实际上和maloca free 是同一种类型,都是一个资源分配函数,一个资源删除函数这种其实和指针一样的类型,它也是不安全的
Dialogue: 0,1:51:25.77,1:51:37.44,Default,,0,0,0,,就如果你定义了一个带有机要硬层的内容,这个东西呢它是它是默认生成一个拷贝的
Dialogue: 0,1:51:37.44,1:51:56.16,Default,,0,0,0,,那你如果一不小心拷贝了,它,就会造成二次释放,也就是GODLE这个text 对象调用了两遍,调用到一个调用到一个text 对象上,就还是double free 的问题,所以也不安全
Dialogue: 0,1:51:56.16,1:52:06.22,Default,,0,0,0,,当然如果你虽然用的是STL容器,而STL容器你装的内容却是一个不安全的对象
Dialogue: 0,1:52:06.22,1:52:20.40,Default,,0,0,0,,比如指针或者这种资源,那也是不安全的,需要你自己去考虑,把它弄成那个呃把它弄成那个深拷贝,或者直接禁止拷贝
Dialogue: 0,1:52:20.40,1:52:21.25,Default,,0,0,0,,这样子
Dialogue: 0,1:52:23.01,1:52:36.43,Default,,0,0,0,,就是如果你的内成员都是安全,这是最好的,那你就什么也不需要声明,你也不需要default ,也不需要delete ,你直接保持默认就可以了
Dialogue: 0,1:52:36.43,1:52:46.62,Default,,0,0,0,,比如我们中有一个叫miss 的类,它是由点,还有这个边啊面啊组成的
Dialogue: 0,1:52:46.62,1:52:53.45,Default,,0,0,0,,它们这些边面都是用victor ,也就是STO容器去管理的
Dialogue: 0,1:52:53.45,1:52:57.62,Default,,0,0,0,,而victor 里的词呢也是非常安全的
Dialogue: 0,1:52:57.62,1:53:08.58,Default,,0,0,0,,比如三维矢量这样,所以他是没有没有必要去自己去实现结构函数拷贝函数这些的
Dialogue: 0,1:53:08.58,1:53:11.62,Default,,0,0,0,,所以它就是一个安全的
Dialogue: 0,1:53:12.39,1:53:22.50,Default,,0,0,0,,但是如果你用到自定义结构函数,那可能就意味着你里面有这种这种管理的资源的对象
Dialogue: 0,1:53:22.50,1:53:32.25,Default,,0,0,0,,所以这是两种情况,一种是管理的资源,也就是他用my lock 和free 这种还有一种是数据结构
Dialogue: 0,1:53:32.25,1:53:38.75,Default,,0,0,0,,数据结构,虽然它对应着某种malaca free ,但是它是可以拷贝的
Dialogue: 0,1:53:39.08,1:53:46.76,Default,,0,0,0,,就是对于管理的资源的那些类,就是我们最好把它的拷贝给删掉
Dialogue: 0,1:53:46.76,1:54:02.52,Default,,0,0,0,,比如我们they know 中有一个新一代的类,然后这个新的它首先是一个SHA,它对应的是GOcreate c 的所创建的C的类,手上面的新的那个巨饼
Dialogue: 0,1:54:02.52,1:54:07.50,Default,,0,0,0,,然后它在结构的时候也会去点亮它这个距离
Dialogue: 0,1:54:07.50,1:54:14.31,Default,,0,0,0,,那么这时候如果你允许拷贝的话,它就会它就会出现重复释放
Dialogue: 0,1:54:14.31,1:54:23.74,Default,,0,0,0,,那你会想,哎,是不是我可以在这里加一个interview count ,从而实现和shell point 一样的引用技术
Dialogue: 0,1:54:23.74,1:54:33.17,Default,,0,0,0,,然后在拷贝的时候,把这个引用技术加一之类的,是不是不就可以避免就重复释放了吗?
Dialogue: 0,1:54:34.42,1:54:36.14,Default,,0,0,0,,没必要没必要
Dialogue: 0,1:54:36.14,1:54:45.65,Default,,0,0,0,,标准库提供了cell point ,你不需要在每一个管理资源的内里去实现一遍这个前拷贝
Dialogue: 0,1:54:45.65,1:54:53.72,Default,,0,0,0,,这个前拷贝还要去管这个ref count 是不是原子的之类的问题,非常麻烦
Dialogue: 0,1:54:53.72,1:55:10.44,Default,,0,0,0,,所以建议统一使用标准库的share point ,只有新的来去管理,而不要直接使用新的的拷贝,这样就可以实现任意没有拷贝函数的对象的前拷贝了
Dialogue: 0,1:55:10.81,1:55:21.24,Default,,0,0,0,,但如果你是数据结构,而这种往往是对应怎么lock free ,这时候它又是可以拷贝的对象
Dialogue: 0,1:55:21.24,1:55:37.82,Default,,0,0,0,,那你可能是需要定义自定义它的拷贝函数的,而不是能直接用share the point 的前拷贝你你的这个拷贝函数必须时间为升拷贝哦,否则也会有的问题
Dialogue: 0,1:55:37.82,1:55:49.85,Default,,0,0,0,,然后函数的参数其实刚才说到funk unique point ,它不是说错嘛,就是因为这样的话是会造成一次拷贝的
Dialogue: 0,1:55:49.85,1:55:57.66,Default,,0,0,0,,就我们以小猪佩奇举例,就我们这里定义了一只猪叫佩奇80公斤
Dialogue: 0,1:55:57.66,1:56:04.11,Default,,0,0,0,,然后我说show page 这时候其实是调用了它的拷贝构造函数的
Dialogue: 0,1:56:05.62,1:56:15.74,Default,,0,0,0,,就是我这里直接写一个pig pig ,其实和直接把这个pig 等于这只pig 是一样,它相当于进行一次拷贝
Dialogue: 0,1:56:15.74,1:56:24.63,Default,,0,0,0,,所以可以看到就是我们小猪佩奇构造以后再去传进去之前出现一次拷贝
Dialogue: 0,1:56:24.63,1:56:27.51,Default,,0,0,0,,如何避免这次拷贝呢?
Dialogue: 0,1:56:27.51,1:56:38.33,Default,,0,0,0,,方法就是在这里声明为pack count ,这样的话就是哎你们还在看吗?
Dialogue: 0,1:56:38.71,1:56:48.07,Default,,0,0,0,,我看得到了没有弹幕,我还以为坏了,就是我们可以加一个const 和,为什么要const 和呢?
Dialogue: 0,1:56:48.07,1:57:01.86,Default,,0,0,0,,就是代表它是一个常引用,就是它虽然不改变pack 的值,但它实际上是指向了外面这个pad ,从而就避免了一次拷贝
Dialogue: 0,1:57:01.86,1:57:12.01,Default,,0,0,0,,就可以看到这里是没有这拷贝一直租了,他就避免一次拷贝,这也可以用于一些不让拷贝的
Dialogue: 0,1:57:12.01,1:57:18.69,Default,,0,0,0,,比如智能有你一个point ,这种不让拷贝的对象也可以用来避免
Dialogue: 0,1:57:18.69,1:57:25.11,Default,,0,0,0,,就比如victor 这种拷贝一次需要ON的复杂度就可以避免
Dialogue: 0,1:57:28.26,1:57:46.36,Default,,0,0,0,,然后呃在哪,然后就是我们这里统一采用pack cos 的和但是有的教材是这样,cos 写在前面的这两个都是一模一样,这都是我个人的一点喜好其实是一样的,不必担心
Dialogue: 0,1:57:46.94,1:57:59.32,Default,,0,0,0,,然后函数参数我们不是说这里可以通过抗测和来避免拷贝嘛,但是不是所有的类都要用cos 和来优化呢,没必要
Dialogue: 0,1:57:59.32,1:58:06.87,Default,,0,0,0,,如果你的这个参数是float 类型,float 一共才32次节,大小32次节
Dialogue: 0,1:58:06.87,1:58:15.22,Default,,0,0,0,,如果你再去传抗日指针,抗日指针是64位的,反而还大了,就不是浪费吗?
Dialogue: 0,1:58:16.04,1:58:31.25,Default,,0,0,0,,所以我们规定对于inter flow 的这种基础类型统一暗自传递,不要引用从原始指针本来就是64位,你再传一个引用还是64位
Dialogue: 0,1:58:31.25,1:58:37.30,Default,,0,0,0,,那你再去解引用,反而浪费时间,就没必要去传一个长引用嘛
Dialogue: 0,1:58:37.30,1:58:40.94,Default,,0,0,0,,所以对于原始纸张我们也统一使用
Dialogue: 0,1:58:40.94,1:58:54.50,Default,,0,0,0,,案子传递,就只有对于数据容器类型,比如victor 或者是我们自定义的这个类型pink ,这时候我们才可以就是通过常饮用来避免一次三拷贝
Dialogue: 0,1:58:54.89,1:59:03.75,Default,,0,0,0,,就是只有数据容器,还有我们自定义的这种可拷贝的类使用这个方法
Dialogue: 0,1:59:03.75,1:59:13.01,Default,,0,0,0,,如果我们这个数据容器本来就不大,比如to pull into into into 是32位,然后to pull into into 就是64位
Dialogue: 0,1:59:13.01,1:59:19.42,Default,,0,0,0,,我们这时候就传一个常引用进去也是64位,好像区别不大嘛
Dialogue: 0,1:59:19.42,1:59:23.21,Default,,0,0,0,,这时候我们直接传值其实问题也不大
Dialogue: 0,1:59:23.21,1:59:26.78,Default,,0,0,0,,如果你想要传引用,其实问题也不大
Dialogue: 0,1:59:27.11,1:59:33.23,Default,,0,0,0,,就是如果容器不大的话,这时候用不用常饮用都差不多
Dialogue: 0,1:59:33.23,1:59:38.29,Default,,0,0,0,,所以说如果你想要简化你的代码也可以不写
Dialogue: 0,1:59:38.29,1:59:43.62,Default,,0,0,0,,就比如vic 3 ,这最多就是64加10 ,呃,呃差不多
Dialogue: 0,1:59:43.62,1:59:52.68,Default,,0,0,0,,然后如果是智能指针的话,特别是西安的point ,这个要注意了,千万不要再去用引用啊
Dialogue: 0,1:59:52.68,1:59:55.61,Default,,0,0,0,,或者就是比如要区分两种
Dialogue: 0,1:59:56.00,2:00:12.41,Default,,0,0,0,,首先是我们刚才说的需要掌管生命周期的那你直接声明为share the point of 别人,或者用那个point 就行了,让用户自己去调用STDmove 就可以了
Dialogue: 0,2:00:12.74,2:00:18.76,Default,,0,0,0,,然后如果不需要生命周期,那你也不要写现在的帮他呀
Dialogue: 0,2:00:18.76,2:00:44.16,Default,,0,0,0,,或者unique path 和也不要就直接写一个原始指针,这样可以就是让用户自己去get 一下这个比如这个modify object ,它只是修改了OBJ里面的数据,而add 是把这个OBJ给他的那个所有权移动给了移动给了另一个,比如全局的OBJlist 之类
Dialogue: 0,2:00:44.16,2:00:49.14,Default,,0,0,0,,这个时候是需要它的智能指针类型来参与的
Dialogue: 0,2:00:49.14,2:00:54.12,Default,,0,0,0,,而如果是只是想修改这个对象,那用原始指针
Dialogue: 0,2:00:54.93,2:00:59.21,Default,,0,0,0,,新客还在听吗?
Dialogue: 0,2:01:01.17,2:01:03.77,Default,,0,0,0,,有人吗有人吗?
Dialogue: 0,2:01:06.37,2:01:16.82,Default,,0,0,0,,顺便一起想要避免这种page ,就比如有个人不小心写了page page ,这就会造成一次隐私的拷贝
Dialogue: 0,2:01:16.82,2:01:27.56,Default,,0,0,0,,如果我想要避免这种莫名其妙的拷贝的话,我可以把它的这个拷贝构造函数声明为explicit 的
Dialogue: 0,2:01:28.72,2:01:35.27,Default,,0,0,0,,就这样就会导致,如果我直接写修配了的话,它这里会出错
Dialogue: 0,2:01:35.27,2:01:53.03,Default,,0,0,0,,因为我必须显示的说pad 括号pad 才能让它通过,这样的话就可以避免一些程序员,就他一不小心把这个写为没有抗死的引用呢,就导致它的效率突然就变低了
Dialogue: 0,2:01:53.03,2:01:57.95,Default,,0,0,0,,我们身为explanation 就让他不要去默认去拷贝
Dialogue: 0,2:01:57.95,2:02:12.97,Default,,0,0,0,,看看V彪有多大600兆,然后我们再说一说为什么 C++ 把拷贝移动搞得这么复杂呢?
Dialogue: 0,2:02:12.97,2:02:19.83,Default,,0,0,0,,为什么像java 这种语言,他们就没有这么复杂的构造函数呢?
Dialogue: 0,2:02:19.83,2:02:32.13,Default,,0,0,0,,因为他们的需求大多是打开数据库,增删改差数据,打开窗口写入文件正则匹配,还有HTB请求之类的
Dialogue: 0,2:02:33.19,2:02:38.02,Default,,0,0,0,,所以说这些东西它其实都是对应的资源
Dialogue: 0,2:02:38.02,2:02:42.05,Default,,0,0,0,,比如打开数据库,数据库不是资源吗?
Dialogue: 0,2:02:42.05,2:03:00.05,Default,,0,0,0,,所以这些对资源来说,我们不是说要那个就是要删除它的那个构造啊,拷贝函数,然后统一用智能指针,就是我们最喜欢的智能指针,又正好是就是引用技术的那种
Dialogue: 0,2:03:00.05,2:03:17.46,Default,,0,0,0,,这时候所以说他们索性简化说一切非基础类型的对象都是前好妹儿啊,然后都有一个引用技术,就不管你有没有自己用CADpond ,它始终是有引用激素的
Dialogue: 0,2:03:17.46,2:03:24.83,Default,,0,0,0,,然后引用激素它为了解决循环引用,它又用了垃圾回收机自动管理
Dialogue: 0,2:03:24.83,2:03:34.06,Default,,0,0,0,,所以说他们这些管资源的语言呢,他们就喜欢把所有非基础都认为是一个新的point
Dialogue: 0,2:03:34.06,2:03:36.69,Default,,0,0,0,,而 C++ 为什么没有呢?
Dialogue: 0,2:03:36.69,2:03:43.81,Default,,0,0,0,,因为 C++ 面向的是系统级编程算法、数据结构,还有高性能计算
Dialogue: 0,2:03:43.81,2:03:58.31,Default,,0,0,0,,而这些里面常常涉及到很多这种就是这种extra 类,它是需要进行一个定义一个的操作,还有赋值的操作,以及甚至像我们pack 这样的一个
Dialogue: 0,2:03:58.86,2:04:06.75,Default,,0,0,0,,总之呢他就是他的业务对象呢是需要知道拷贝移动指针这些概念的
Dialogue: 0,2:04:06.75,2:04:12.75,Default,,0,0,0,,所以说他才发展出了三无法的那些乱七八糟的东西
Dialogue: 0,2:04:13.77,2:04:29.31,Default,,0,0,0,,所以说我们如果想学好高性能计算的话,一定要学 C++ 哦,不要学那个打开数据库用的java ,千万不要搞错了
Dialogue: 0,2:04:29.31,2:04:45.55,Default,,0,0,0,,好了,今天的课程就快要结束了,然后我准备了一些扩展阅读关键字,有兴趣的同学可以学习一下
Dialogue: 0,2:04:45.55,2:04:52.20,Default,,0,0,0,,首先是PIMPO模式,它可以分离声明和定义
Dialogue: 0,2:04:52.20,2:05:00.17,Default,,0,0,0,,就你改一下那个类里面的属性,它外面也不会重新编一遍
Dialogue: 0,2:05:00.17,2:05:02.16,Default,,0,0,0,,黑的好吗?
Dialogue: 0,2:05:02.16,2:05:14.39,Default,,0,0,0,,然后还有虚函数,这个是用 C++ 事后一些数据库方面的需求的时候会用到这些,然后拷贝虚函数
Dialogue: 0,2:05:14.39,2:05:22.08,Default,,0,0,0,,这是比如就是拷贝构造函数,不是构造函数嘛,构造函数是不能委屈的
Dialogue: 0,2:05:22.08,2:05:30.83,Default,,0,0,0,,如果我想要把拷贝定义为虚呢,就比如我一个pack 继承了一个animal ,而pad 希望拷贝
Dialogue: 0,2:05:30.83,2:05:36.39,Default,,0,0,0,,然后我希望通过animal 接口去拷贝,这时候怎么办呢?
Dialogue: 0,2:05:36.39,2:05:50.00,Default,,0,0,0,,可以用一个clone ,你就是把column 声明为一个虚虚函数,然后clone 返回类型就是shared point ,然后share the point 他就可以实现拷贝了
Dialogue: 0,2:05:50.80,2:05:54.52,Default,,0,0,0,,对呀对呀,我就是看不起家哈
Dialogue: 0,2:05:54.52,2:06:09.04,Default,,0,0,0,,然后还有一个就是unique pointer release ,就是我们不是说unique pointer 在他那个叫什就是在它结构的时候不是会自动删除这个delete 嘛
Dialogue: 0,2:06:09.04,2:06:17.12,Default,,0,0,0,,那如果我突然回心转意说哎呀,我想我现在不想删除了,我想把它给到另一个
Dialogue: 0,2:06:17.12,2:06:26.97,Default,,0,0,0,,比如一些老代码,它使用了删除,这时候就可以用人例子来获取unique point 中的原始指针而不删除
Dialogue: 0,2:06:27.67,2:06:32.94,Default,,0,0,0,,然后share the point from this , 就是this 不是一个原始指针嘛
Dialogue: 0,2:06:32.94,2:06:36.95,Default,,0,0,0,,用了这个以后,this 就会变成一个shared point
Dialogue: 0,2:06:36.95,2:06:52.17,Default,,0,0,0,,但是它的限制在于shared pond 必须变成就是变成你这个类只能通过make share 的来构建,就不能再自己去new ,或者从站上分配啊,你有兴趣吗?
Dialogue: 0,2:06:54.00,2:06:57.57,Default,,0,0,0,,你是说从CPY里调用CBP吗?
Dialogue: 0,2:06:57.57,2:07:19.03,Default,,0,0,0,,我推荐一下,你看这个推荐这个PY版的十一,我推荐这个它能够把 C++ 的很多数据结构,比如victor ,还有突破这种结构直接和派送共享
Dialogue: 0,2:07:19.36,2:07:40.68,Default,,0,0,0,,对呀对呀,我们这一路也在用这个,虽然最近不怎么用了,然后dynamic cast 这个又是一个谷歌说不好的,但我其实经常用它可以就是把具有虚函数的类去类型转换
Dialogue: 0,2:07:40.68,2:07:46.68,Default,,0,0,0,,然后就不需要知道原来是什么类型dynamic pointer 开始呢
Dialogue: 0,2:07:46.68,2:08:01.57,Default,,0,0,0,,因为dynamic 开始只能针对原始指针,所以又发明了按照那个portal test ,它能够对智能指针进行这个这个dynamic case 的功能运算符重载
Dialogue: 0,2:08:01.57,2:08:04.13,Default,,0,0,0,,刚刚说了operator 身份证
Dialogue: 0,2:08:04.46,2:08:13.62,Default,,0,0,0,,唉,对呀,我也想用这个呀,就是PY办的很啊,泰迪是PY办的,太极是PY版的
Dialogue: 0,2:08:13.62,2:08:18.82,Default,,0,0,0,,但是PY版的很烦的一点就是它锁定PY版本
Dialogue: 0,2:08:18.82,2:08:25.58,Default,,0,0,0,,一旦你通过PY3.8编译了,你就不能在3.6里去使用它
Dialogue: 0,2:08:25.58,2:08:41.38,Default,,0,0,0,,所以我们现在也在试着转换到c types ,然后幼稚引用就是我们刚才不是说到移动和拷贝嘛,为什么两个和就代表一种抗的和就代表拷贝呢?
Dialogue: 0,2:08:41.38,2:08:48.70,Default,,0,0,0,,你可以去了解一下幼稚引用,你可以通过BE点com 他们已经恢复了
Dialogue: 0,2:08:48.70,2:08:53.93,Default,,0,0,0,,然后你去搜这个幼稚引用,你就能知道更多信息
Dialogue: 0,2:08:55.07,2:09:01.46,Default,,0,0,0,,然后如果你不想知道的话,我们下一讲也会讲到幼稚引用
Dialogue: 0,2:09:01.46,2:09:03.33,Default,,0,0,0,,所以说不用担心
Dialogue: 0,2:09:03.33,2:09:08.66,Default,,0,0,0,,对呀,他甚至不需要链接拍送的那个库就很方便
Dialogue: 0,2:09:09.57,2:09:27.88,Default,,0,0,0,,然后还有这两个听起来很神奇的东西,他可以就是他这个share point 偶尔都可以接受任何一个对象的指针,而且也能智能的管理它和C语言的Y的层一样
Dialogue: 0,2:09:27.88,2:09:38.96,Default,,0,0,0,,但是它能够管理生命周期,然后CSCDany 呢是一个三拷贝版本的share point of void ,它能够接受任何的对象
Dialogue: 0,2:09:38.96,2:09:47.27,Default,,0,0,0,,比如in 它,比如victor 都可以,但它拷贝的时候会变成一个拷贝,这是它唯一的缺点
Dialogue: 0,2:09:47.72,2:09:56.78,Default,,0,0,0,,然后你可以用这个这个用这个去搜啊,不要用这个,不要用广告搜索引擎哦,不要哦
Dialogue: 0,2:09:56.78,2:10:04.51,Default,,0,0,0,,然后如果你感兴趣的话,我可以专门开一张讲这些动态多态里的知识
Dialogue: 0,2:10:04.51,2:10:10.38,Default,,0,0,0,,不过其实在高性能计算领域用的更多的是静态多态
Dialogue: 0,2:10:10.38,2:10:20.87,Default,,0,0,0,,而这个我们下一章会讲,嗯,然后就是回家作业,我们这门课的回家作业是在这个地址上
Dialogue: 0,2:10:21.20,2:10:42.51,Default,,0,0,0,,我看一下,就是这是我们第一课的回家作业,还有你看已经有三四个同学提交作业了,看就是approve ,就是我批改过的作业,这些我待会儿会去批的
Dialogue: 0,2:10:43.21,2:10:56.32,Default,,0,0,0,,然后这是我们第二课的回家作业,这里面的内容就是利用今天学到的智能指针知识,我们实现了一个双向链表类
Dialogue: 0,2:10:56.32,2:11:08.06,Default,,0,0,0,,然后在双向链表内呢,有一个问题就是它这个拷贝是前拷贝,我要求你把它实现为升拷贝请实现
Dialogue: 0,2:11:08.39,2:11:12.50,Default,,0,0,0,,然后这里还有一些细枝末节的优化
Dialogue: 0,2:11:12.50,2:11:19.09,Default,,0,0,0,,比如这个如果你听课,你应知道会怎么做吧,嗯去做做看吧
Dialogue: 0,2:11:19.42,2:11:25.14,Default,,0,0,0,,然后你可以通过P2来提交作业,怎么提交P2呢?
Dialogue: 0,2:11:25.88,2:11:31.22,Default,,0,0,0,,需要我讲一下怎么提交PM啊
Dialogue: 0,2:11:31.22,2:11:39.23,Default,,0,0,0,,对呀,编译期编译时候的多态需要讲一下怎么提交PR吗?
Dialogue: 0,2:11:39.23,2:11:48.96,Default,,0,0,0,,都会提交PR吧,不需要了,能不讲了
Dialogue: 0,2:11:51.04,2:11:59.22,Default,,0,0,0,,可以看一下这个HW01 ,他们都提交了这个这有一个什么好处?
Dialogue: 0,2:11:59.22,2:12:05.16,Default,,0,0,0,,就是嗯可以在这里写一些你的实现原理
Dialogue: 0,2:12:05.16,2:12:16.79,Default,,0,0,0,,我的实现原理我是一个看分的重点,就是看完成作业的要求15到50分的,然后用自己的话解释
Dialogue: 0,2:12:16.79,2:12:20.89,Default,,0,0,0,,如果你不解释,25分就没了就没了
Dialogue: 0,2:12:20.89,2:12:23.96,Default,,0,0,0,,然后你的代码是不是规范呢?
Dialogue: 0,2:12:23.96,2:12:26.52,Default,,0,0,0,,是不是跨平台也占五分
Dialogue: 0,2:12:26.52,2:12:30.88,Default,,0,0,0,,然后如果你有自己的创新点,我也会加分
Dialogue: 0,2:12:30.88,2:12:40.11,Default,,0,0,0,,比如你把list 改成了迭代器模式,或者变成一个模板类,那也会给你加分,最多加20分哦
Dialogue: 0,2:12:40.44,2:12:43.50,Default,,0,0,0,,然后我为什么要用P2呢?
Dialogue: 0,2:12:43.50,2:12:56.25,Default,,0,0,0,,因为这样你们改了什么,我就立马能看见,这是被删了,这是被新增的怎样还还在看吗?
Dialogue: 0,2:12:57.94,2:13:00.60,Default,,0,0,0,,你们会用PR吗?
Dialogue: 0,2:13:06.71,2:13:18.71,Default,,0,0,0,,总之就是有很多教程,哎呀,哎呀不小心的,总之就结束了
Dialogue: 0,2:13:18.71,2:13:24.20,Default,,0,0,0,,然后这是我们的课件,它就是HW02和cos
Dialogue: 0,2:13:24.20,2:13:37.35,Default,,0,0,0,,然后这是我的空间,你可以去关注一下我就是在这里,我待会儿就会把录播传上来了,怎么样?
Dialogue: 0,2:13:40.14,2:13:46.68,Default,,0,0,0,,好啦好啦,那我要停掉了
Dialogue: 0,2:13:47.34,2:13:53.90,Default,,0,0,0,,不是我说的PR不是阿杜比的那个我先停掉了