之前人人人面试的时候开了外放,嫖到了一波面试题,问了许多c++,正巧把一些常问的问题总结下,顺带复习一波
仅为面试复习用,具体内容参考<<c++反汇编与逆向分析技术揭秘>>,毕竟本人c++也不咋滴233。
引用
一般都会问引用和指针区别
这个很容易,引用本质上就是指针,都是一块内存放了某个变量的地址,至于为什么有引用主要是安全,但这个安全也只是针对编译来说的,引用不可修改而指针可以,本质上还是个指针只不过是编译器来维护。
虚表
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; class Base { public: void Function_1() { printf("Function_1...\n"); } virtual void Function_2() { printf("Function_2...\n"); } };
int main() { Base base; base.Function_1(); base.Function_2(); Base* p = &base; p->Function_1(); p->Function_2(); return 0; }
|
在分情况讨论虚表时先给个例子

可见如果是通过对象调用的话是直接调用的
但如果是指针调用那就会涉及虚表,可以看到间接call,当然因为编译器版本问题可能有些出入。
再来个例子帮助更好理解虚表
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; class Base { public: int x; int y; virtual void Function_1() { printf("Function_1...\n"); } virtual void Function_2() { printf("Function_2...\n"); } };
int main() { Base base; printf("%d", sizeof(base)); return 0; }
|
含有虚函数的类成员第一项是个指针指向虚表,虚表放的是各个虚函数地址,所以这边大小为12,即使定义6个虚函数大小还是12.
|
|
|
虚函数表 |
|
|
|
|
Base对象 |
0x123245 |
—> |
0x123456 |
|
Function_1() |
|
|
|
.. |
|
0x123456 |
|
Function_2() |
|
|
|
.. |
|
0x123456 |
|
Function_3() |
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
下面分几个情况讨论下
单继承无覆盖
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base { public: virtual void Function_1() { printf("Base:Function_1...\n"); } virtual void Function_2() { printf("Base:Function_2...\n"); } virtual void Function_3() { printf("Base:Function_3...\n"); } }; struct Sub :Base { public: virtual void Function_4() { printf("Sub:Function_4...\n"); } virtual void Function_5() { printf("Sub:Function_5...\n"); } virtual void Function_6() { printf("Sub:Function_6...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
typedef void(*pFunction)(void);
pFunction pFn;
for (int i = 0; i < 6; i++) { pFn = (pFunction) * ((int*)(*(int*)&sub) + i); pFn(); }
return 0; }
|
|
|
|
虚函数表 |
|
|
|
Sub对象 |
0x123245 |
—> |
0x123456 |
|
Base:Function_1 |
|
|
.. |
|
0x123457 |
|
Base:Function_2 |
|
|
.. |
|
0x135466 |
|
Base:Function_3 |
|
|
.. |
|
0x135466 |
|
Sub:Function_4 |
|
|
.. |
|
0x135466 |
|
Sub:Function_5 |
|
|
其他成员 |
|
0x135466 |
|
Sub:Function_6 |
|
|
|
|
00000000 |
|
|
|
单继承有覆盖
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base { public: virtual void Function_1() { printf("Base:Function_1...\n"); } virtual void Function_2() { printf("Base:Function_2...\n"); } virtual void Function_3() { printf("Base:Function_3...\n"); } }; struct Sub :Base { public: virtual void Function_1() { printf("Sub:Function_1...\n"); } virtual void Function_2() { printf("Sub:Function_2...\n"); } virtual void Function_6() { printf("Sub:Function_6...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
typedef void(*pFunction)(void);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
printf("%x\n", *((int*)(*(int*)&sub) + 6));
return 0; }
|
|
|
|
虚函数表 |
|
|
|
Sub对象 |
0x123245 |
—> |
0x123456 |
|
Sub:Function_1 |
|
|
.. |
|
0x123457 |
|
Sub:Function_2 |
|
|
.. |
|
0x135466 |
|
Base:Function_3 |
|
|
.. |
|
0x135466 |
|
Sub:Function_6 |
|
|
.. |
|
00000000 |
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
多继承无覆盖
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base1 { public: virtual void Fn_1() { printf("Base1:Fn_1...\n"); } virtual void Fn_2() { printf("Base1:Fn_2...\n"); } }; struct Base2 { public: virtual void Fn_3() { printf("Base2:Fn_3...\n"); } virtual void Fn_4() { printf("Base2:Fn_4...\n"); } }; struct Sub :Base1, Base2 { public: virtual void Fn_5() { printf("Sub:Fn_5...\n"); } virtual void Fn_6() { printf("Sub:Fn_6...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
typedef void(*pFunction)(void);
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
printf("Sub 的虚函数表地址为:%x\n", *(int*)((int)&sub + 4));
pFunction pFn1;
for (int k = 0; k < 2; k++) { int temp = *((int*)(*(int*)((int)&sub + 4)) + k); pFn1 = (pFunction)temp; pFn1(); }
return 0; }
|
多继承就有俩虚表了这边注意
Sub对象 |
0x123245 |
—> |
Fn_1() |
Fn_2() |
Sub:Fn_5 |
Sub:Fn_6 |
|
|
0x345678 |
—> |
|
|
|
|
|
|
.. |
|
Fn_3() |
Fn_4() |
|
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
此时Sub对象的大小为8字节 |
|
|
|
|
|
|
多继承有覆盖
情形1
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base1 { public: virtual void Fn_1() { printf("Base1:Fn_1...\n"); } virtual void Fn_2() { printf("Base1:Fn_2...\n"); } }; struct Base2 { public: virtual void Fn_3() { printf("Base2:Fn_3...\n"); } virtual void Fn_4() { printf("Base2:Fn_4...\n"); } }; struct Sub :Base1, Base2 { public: virtual void Fn_1() { printf("Sub:Fn_1...\n"); } virtual void Fn_3() { printf("Sub:Fn_3...\n"); } virtual void Fn_5() { printf("Sub:Fn_5...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
typedef void(*pFunction)(void);
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
printf("Sub 的虚函数表地址为:%x\n", *(int*)((int)&sub + 4));
pFunction pFn1;
for (int k = 0; k < 2; k++) { int temp = *((int*)(*(int*)((int)&sub + 4)) + k); pFn1 = (pFunction)temp; pFn1(); }
return 0; }
|
|
Sub对象 |
0x123245 |
—> |
Sub:Fn_1 |
Base1:Fn_2 |
Sub:Fn_5 |
|
|
|
|
0x345678 |
—> |
|
|
|
|
|
|
|
.. |
|
Sub:Fn_3 |
Base2:Fn_4 |
|
|
|
|
|
.. |
|
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
此时Sub对象的大小为8字节 |
|
|
|
|
|
|
情形2
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base1 { public: virtual void Fn_1() { printf("Base1:Fn_1...\n"); } virtual void Fn_2() { printf("Base1:Fn_2...\n"); } }; struct Base2 :Base1 { public: virtual void Fn_3() { printf("Base2:Fn_3...\n"); } virtual void Fn_4() { printf("Base2:Fn_4...\n"); } }; struct Sub :Base2 { public: virtual void Fn_5() { printf("Sub:Fn_5...\n"); } virtual void Fn_6() { printf("Sub:Fn_6...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
printf("%x\n", sizeof(sub));
typedef void(*pFunction)(void);
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
return 0; }
|
|
|
|
|
虚函数表 |
|
|
|
|
Sub对象 |
0x123245 |
—> |
0x123456 |
|
Base1:Fn_1() |
|
|
|
.. |
|
0x123457 |
|
Base1:Fn_2() |
|
|
|
.. |
|
0x135466 |
|
Base2:Fn_3() |
|
|
|
.. |
|
0x135466 |
|
Base2:Fn_4() |
|
|
|
.. |
|
0x135466 |
|
Sub:Fn_5() |
|
|
|
其他成员 |
|
0x135466 |
|
Sub:Fn_6() |
|
|
|
|
|
00000000 |
|
|
|
情形3
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base1 { public: virtual void Fn_1() { printf("Base1:Fn_1...\n"); } virtual void Fn_2() { printf("Base1:Fn_2...\n"); } }; struct Base2 :Base1 { public: virtual void Fn_1() { printf("Base2:Fn_1...\n"); } virtual void Fn_3() { printf("Base2:Fn_3...\n"); } }; struct Sub :Base2 { public: virtual void Fn_5() { printf("Sub:Fn_5...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
printf("%x\n", sizeof(sub));
typedef void(*pFunction)(void);
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
return 0; }
|
|
|
|
|
虚函数表 |
|
|
|
|
|
Sub对象 |
0x123245 |
—> |
Base2:Fn_1 |
Base1:Fn_2 |
Base2:Fn_3 |
Sub:Fn_5 |
|
|
|
.. |
|
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
情形4
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base1 { public: virtual void Fn_1() { printf("Base1:Fn_1...\n"); } virtual void Fn_2() { printf("Base1:Fn_2...\n"); } }; struct Base2 :Base1 { public: virtual void Fn_1() { printf("Base2:Fn_1...\n"); } virtual void Fn_3() { printf("Base2:Fn_3...\n"); } }; struct Sub :Base2 { public: virtual void Fn_1() { printf("Sub:Fn_1...\n"); } virtual void Fn_5() { printf("Sub:Fn_5...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
printf("%x\n", sizeof(sub));
typedef void(*pFunction)(void);
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
return 0; }
|
|
|
|
|
虚函数表 |
|
|
|
|
Sub对象 |
0x123245 |
—> |
Sub:Fn_1 |
Base1:Fn_2 |
Base2:Fn_3 |
Sub:Fn_5 |
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
|
情形5
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> using namespace std; struct Base1 { public: virtual void Fn_1() { printf("Base1:Fn_1...\n"); } virtual void Fn_2() { printf("Base1:Fn_2...\n"); } }; struct Base2 :Base1 { public: virtual void Fn_3() { printf("Base2:Fn_3...\n"); } }; struct Sub :Base2 { public: virtual void Fn_1() { printf("Sub:Fn_1...\n"); } virtual void Fn_3() { printf("Sub:Fn_3...\n"); } }; int main(int argc, char* argv[]) { Sub sub;
printf("%x\n", sizeof(sub));
typedef void(*pFunction)(void);
printf("Sub 的虚函数表地址为:%x\n", *(int*)&sub);
pFunction pFn;
for (int i = 0; i < 6; i++) { int temp = *((int*)(*(int*)&sub) + i); if (temp == 0) { break; } pFn = (pFunction)temp; pFn(); }
return 0; }
|
|
|
|
|
|
|
|
|
|
|
|
|
虚函数表 |
|
|
|
|
Sub对象 |
0x123245 |
—> |
Sub:Fn_1 |
Base1:Fn_2 |
Sub:Fn_3 |
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
.. |
|
|
|
|
|
|
|
其他成员 |
|
|
|
|
|
|
|
|
|
|
|
|
|
主要是第一个情形要分清楚
其他几个都差不多
STL
Standard Template Library 标准模板库
前面讲的这些都是基础中的基础了,如果面试官往难了问一般问stl或者智能指针,但是一般不会问这些因为不是搞开发。。。
智能指针
unique_ptr 拥有独有对象所有权语义的智能指针
shared_ptr 拥有共享对象所有权语义的智能指针
weak_ptr 到 std::shared_ptr 所管理对象的弱引用
unique_ptr && shared_ptr
unique_ptr和shared_ptr是俩个主要的智能指针
unique_ptr是通过指针占有并管理另一对象,并在 unique_ptr 离开作用域时释放该对象的智能指针。在下列两者之一发生时用关联的删除器释放对象
- 销毁了管理的 unique_ptr 对象
- 通过 operator= 或 reset() 赋值另一指针给管理的 unique_ptr 对象。
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> #include <memory> using namespace std;
struct person { ~person() { cout << "~person\n"; } }; int main() { unique_ptr<person> pointer(new person); return 0; }
|
unique_ptr在离开作用域时会自动帮你释放内存而不需要手动delete,所以叫“智能”。
有个特点就是对象只能被一个指针占有,代码如下
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> #include <memory> #include <string> using namespace std;
struct person { ~person() { cout << "~person\n"; } string str; }; unique_ptr<person> test() { return unique_ptr<person>(new person); } int main() { unique_ptr<person> pointer = test(); pointer->str = "hello"; unique_ptr<person> p2 = move(pointer); if (!pointer) { cout << "pointer为空\n"; } if (p2) { cout << "p2不为空\n"; } return 0; }
|

反编译康康
有c++逆向内味了

随便一个函数就占了近100行
再看看shared_ptr
如果理解了上面的,理解这个很容易,多了个方法就是查看引用计数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> #include <memory> #include <string> using namespace std; int main() { shared_ptr<string> sp(new string("hello")); cout << sp.use_count() << "\n"; cout << *sp << "\n"; shared_ptr<string> sp1 = sp; cout << sp.use_count() << "\n"; return 0; }
|
下面就要讲下智能指针的问题了
安全隐患
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> #include <memory> #include <string> using namespace std; struct person { void show() { cout << "person\n"; } shared_ptr<person> getshared() { return shared_ptr<person>(this); } }; int main() { shared_ptr<person> ptr(new person); shared_ptr<person> ptr2 = ptr->getshared(); cout << ptr.use_count() << "\n"; return 0; }
|
打印出来的结果是1,所以当main函数结束后,ptr释放了,计数-1,此时ptr2还指向一个被释放的内存,这就出现了内存泄漏。
想要解决问题的话得用另一个模板
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
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> #include <memory> #include <string> using namespace std; struct person :enable_shared_from_this<person>{ void show() { cout << "person\n"; } shared_ptr<person> getshared() { return shared_from_this(); } }; int main() { shared_ptr<person> ptr(new person); shared_ptr<person> ptr2 = ptr->getshared(); cout << ptr.use_count() << "\n"; return 0; }
|
当然问题不止这个
比如用裸指针创建时
1 2 3 4 5 6 7 8 9 10 11 12 13
| void main( ) {
int* p = new int; shared_ptr<int> sptr1( p); shared_ptr<int> sptr2( p );
shared_ptr<int> sptr1( new int ); shared_ptr<int> sptr2 = sptr1; shared_ptr<int> sptr3; sptr3 =sptr1 }
|
STRING
内存布局前16个为字符空间,这是当字符长度小于16时,后面一个unsigned int表示目前字符串长度,在后面一个表示容量capacity
当长度大于容量时会扩容
当长度大于15时,内存布局开头会变成一个指针,指针指向处为字符串
VECTOR
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #define _CRT_SECURE_NO_DEPRECATE #include <stdio.h> #include <windows.h> #include <tlhelp32.h> #include <stdlib.h> #include <string.h> #include <vector> #include <iostream> #include <memory> #include <string> using namespace std;
int main() { vector<int> test1(); vector<int> test2(5); vector<int> test3(5,3); vector<int> test4(test3); vector<int> test5(test4.begin(),test4.end()); return 0; }
|
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
| int __cdecl main(int argc, const char **argv, const char **envp) { int v3; int v4; int v6; int v7; int v8; char v9; int v10; int v11; int v12; int v13; int v14; int v15; int v16; int *v17; char *v18; int v19; char v20; int v21;
__CheckForDebuggerJustMyCode(&unk_424033); std::vector<int,std::allocator<int>>::__autoclassinit2(0x10u); v3 = std::allocator<int>::allocator<int>(v13, v14); std::vector<int,std::allocator<int>>::vector<int,std::allocator<int>>(5, v3); v21 = 0; std::vector<int,std::allocator<int>>::__autoclassinit2(0x10u); v19 = 3; v4 = std::allocator<int>::allocator<int>(v13, v14); std::vector<int,std::allocator<int>>::vector<int,std::allocator<int>>(5, &v19, v4); LOBYTE(v21) = 1; std::vector<int,std::allocator<int>>::__autoclassinit2(0x10u); std::vector<int,std::allocator<int>>::vector<int,std::allocator<int>>(&v20); LOBYTE(v21) = 2; std::vector<int,std::allocator<int>>::__autoclassinit2(0x10u); v12 = std::allocator<int>::allocator<int>(v13, v14); v18 = &v9; std::vector<int,std::allocator<int>>::end(&v9); v17 = &v6; std::vector<int,std::allocator<int>>::begin(&v6); v15 = std::vector<int,std::allocator<int>>::vector<int,std::allocator<int>>(v6, v7, v8, v9, v10, v11, v12); v16 = 0; std::vector<int,std::allocator<int>>::~vector<int,std::allocator<int>>(v13, v14); LOBYTE(v21) = 1; std::vector<int,std::allocator<int>>::~vector<int,std::allocator<int>>(v13, v14); LOBYTE(v21) = 0; std::vector<int,std::allocator<int>>::~vector<int,std::allocator<int>>(v13, v14); v21 = 0xFFFFFFFF; std::vector<int,std::allocator<int>>::~vector<int,std::allocator<int>>(v13, v14); return v16; }
|
配合源码看起来容易学
vector a的第一个字段是size 大小第二个字段是capacity 容量
和std::string
差不多
当size>capacity
也就是空间不够用时
首先配置一块新空间,然后将元素从旧空间一一搬往新空间,再把旧空间归还给操作系统