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


关于c++
http://www.psbazx.com/2020/10/04/关于c/
Beitragsautor
皮三宝
Veröffentlicht am
October 3, 2020
Urheberrechtshinweis