关于c++

之前人人人面试的时候开了外放,嫖到了一波面试题,问了许多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;
}

在分情况讨论虚表时先给个例子

image-20201004111321286

可见如果是通过对象调用的话是直接调用的

但如果是指针调用那就会涉及虚表,可以看到间接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 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 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 sub;

//通过函数指针调用函数,验证正确性
typedef void(*pFunction)(void);


//对象的前四个字节是第一个Base1的虚表
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();
}

//对象的第二个四字节是Base2的虚表
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 sub;

//通过函数指针调用函数,验证正确性
typedef void(*pFunction)(void);


//对象的前四个字节是第一个Base1的虚表
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();
}

//对象的第二个四字节是Base2的虚表
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 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 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 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 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离开作用域,指针所包含的内容会被释放。
unique_ptr<person> pointer(new person);
//person *a = 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;
}

image-20201004194754698

反编译康康

有c++逆向内味了

image-20201004194936044

随便一个函数就占了近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); // count 1
shared_ptr<int> sptr2( p ); // count 1

// 正确
shared_ptr<int> sptr1( new int ); // count 1
shared_ptr<int> sptr2 = sptr1; // count 2
shared_ptr<int> sptr3;
sptr3 =sptr1 // count 3
}

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; // eax
int v4; // eax
int v6; // [esp-1Ch] [ebp-1B4h]
int v7; // [esp-18h] [ebp-1B0h]
int v8; // [esp-14h] [ebp-1ACh]
char v9; // [esp-10h] [ebp-1A8h]
int v10; // [esp-Ch] [ebp-1A4h]
int v11; // [esp-8h] [ebp-1A0h]
int v12; // [esp-4h] [ebp-19Ch]
int v13; // [esp+0h] [ebp-198h]
int v14; // [esp+4h] [ebp-194h]
int v15; // [esp+10h] [ebp-188h]
int v16; // [esp+18h] [ebp-180h]
int *v17; // [esp+24h] [ebp-174h]
char *v18; // [esp+30h] [ebp-168h]
int v19; // [esp+48h] [ebp-150h]
char v20; // [esp+15Ch] [ebp-3Ch]
int v21; // [esp+194h] [ebp-4h]

__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也就是空间不够用时
首先配置一块新空间,然后将元素从旧空间一一搬往新空间,再把旧空间归还给操作系统

文章目录
  1. 1. 引用
  2. 2. 虚表
    1. 2.1. 单继承无覆盖
    2. 2.2. 单继承有覆盖
    3. 2.3. 多继承无覆盖
    4. 2.4. 多继承有覆盖
      1. 2.4.1. 情形1
      2. 2.4.2. 情形2
      3. 2.4.3. 情形3
      4. 2.4.4. 情形4
      5. 2.4.5. 情形5
  3. 3. STL
    1. 3.1. 智能指针
      1. 3.1.1. unique_ptr && shared_ptr
      2. 3.1.2. 安全隐患
    2. 3.2. STRING
    3. 3.3. VECTOR
|