2
2
:toc:
3
3
4
4
// 保证所有的目录层级都可以正常显示图片
5
- :path: C++知识点总结 /
5
+ :path: C++/
6
6
:imagesdir: ../image/
7
7
8
8
// 只有book调用的时候才会走到这里
@@ -75,6 +75,7 @@ struct _Vector_impl
75
75
pointer _M_end_of_storage;
76
76
};
77
77
----
78
+
78
79
- list: 双向链表
79
80
- map: 底层红黑树
80
81
- deque: 双端队列
@@ -86,6 +87,11 @@ struct _Vector_impl
86
87
87
88
88
89
=== 虚函数
90
+
91
+ // 虚函数实现原理,这里说明
92
+
93
+
94
+
89
95
==== 虚函数实现
90
96
C++多态分为静态多态(编译时多态)和动态多态(运行时多态)两大类,静态多态通过重载,模板来实现;动态多态是通过虚函数实现。
91
97
虚函数通过虚函数表vtbl(virtual table)和虚函数表指针vptr(virtual table pointer)来实现动态多态。当调用一个虚函数时,被执行的代码和调用函数的对象的动态类型相一致,当一个类声明了虚函数或者继承了虚函数,这个类就会有自己的vtbl,vtbl实际上就是一个函数指针数组,有的编译器用的是链表,不过方法都差不多。vtbl中每一个元素都对应一个函数指针,函数指针指向该类的一个虚函数,实际上每一个对象都会包含一个vptr,vptr指向该类的vtbl;
@@ -305,6 +311,9 @@ Logger *lpLog = &database; // 错误,基类指针不能指向私有继承的
305
311
306
312
=== 内存分配
307
313
314
+ //C++中虚拟内存映射规则
315
+
316
+
308
317
- 静态存储区分配。内存在程序编译期间就已经分配好,这块内存在程序整个运行期间都存在,例如全局变量,static 变量
309
318
- 在栈上创建,在执行函数时,函数内部局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放,栈内存分配运算内置于处理器的指令集中,效率很高,但是分配器的内存容量有限。
310
319
- 从堆上分配,亦称为动态分配,程序在运行的时候Malloc或者new申请任意多的内存,程序员自己负责在何时用free或delete释放内存,动态内存的生存期由我们决定,使用灵活,但是问题也多
@@ -331,6 +340,16 @@ f. sizeof引用是引用对象的大小,sizeof指针是指针本身的大小
331
340
g. 指针和引用搞得自增(++)运算意义不一样
332
341
h. 从内存分配上来看,程序为指针分配内存区域,而引用不需要分配内存区域
333
342
343
+ ==== C++ 中为什么能用引用尽量不要用指针
344
+
345
+ 1. 引用是变量的别名,代码清晰度更高
346
+ 2. 避免不必要的参数检查
347
+ 3. 引用无需解引用
348
+
349
+ 其中第3点需要特别说一下,指针本身也是个变量,那么也存在自己的地址,每次通过指针调用对象,需要先通过指针变量的名字找到指针的地址,指针地址上又存储了对象所在的地址,需要取出来再找到具体对象所在的位置。
350
+
351
+ image::cpp/image-2024-10-15-09-48-20-744.png[]
352
+
334
353
==== 智能指针
335
354
====
336
355
智能指针:实际上行为类似于指针的类对象,它的一种通用实现方法是采用引用计数的方法
@@ -502,6 +521,7 @@ this指针是右值
502
521
503
522
504
523
==== volatile作用
524
+
505
525
1. volatile关键词的第一个特性:易变性。所谓的易变性,在汇编层面反应出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。
506
526
2. volatile关键词的第二个特性:不可优化特性,volatile告诉编译器不要对我这个变量进行各种激进的优化,甚至将变量直接消除,保证程序员写在代码中的指令一定会被执行。
507
527
3. volatile关键词第三个特性:顺序性。能够保证volatile变量间的顺序行,编译器不会进行乱序优化。
@@ -800,14 +820,17 @@ class C : virtual public B
800
820
A:仍然是4+1+3(补齐) = 8
801
821
B:4+1+3 + 4(vptr)+1(c2)+3(补齐) = 16
802
822
C;4+1+3 + 4(vptr)+1(c2)+3(补齐) + 4(vptr)+1(c3)+3(补齐) = 24
823
+
803
824
64位g++下:
804
825
A:仍然是4+1+3(补齐) = 8
805
826
B:4+1+3 + 8(vptr)+1(c2)+7(补齐) = 24
806
827
C;4+1+3 + 8(vptr)+1(c2)+7(补齐) + 8(vptr)+1(c3)+7(补齐) = 40
828
+
807
829
vs2013下:
808
830
A:仍然是4+1+3(补齐) = 8
809
831
B:4+1+3 + 4(vptr)+1(c2)+3(补齐) = 16
810
832
C;4+1+3 + 4(vptr)+1(c2)+3(补齐) + 4(vptr)+1(c3)+3(补齐) = 24
833
+
811
834
注意这里vs2013的情况表面看上去和32位g++相同,实则不然。例如去掉class B对于A的虚拟继承性
812
835
****
813
836
@@ -855,50 +878,17 @@ public:
855
878
856
879
857
880
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
881
=== 工具
893
882
894
883
==== sourcetrail
895
- image::../image/image-2024-07-31-09-43-05-019.png[]
896
884
897
- image::../image/image-2024-07-31-09-44-08-226.png[]
885
+ image::image-2024-07-31-09-43-05-019.png[]
886
+
887
+ image::image-2024-07-31-09-44-08-226.png[]
898
888
899
889
==== Understand
900
890
901
- image::../image/ image-2024-07-31-09-44-44-147.png[]
891
+ image::image-2024-07-31-09-44-44-147.png[]
902
892
903
893
904
894
0 commit comments