C++容器renew导致的指针失效

问题场景:

以vector为例,有时候我们会把原始数据列表作为vector数组,同时把需要排序或其他处理的数组使用指向原始vector的迭代器数组

示例代码:

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5  
 6 class Person
 7 {
 8 public:
 9     Person()
10     {
11         age = 0;
12     }
13  
14     string name;
15     int age;
16 };
17  
18 typedef vector<Person>::iterator PersonPtr;
19  
20 int main(int argc, char* argv[])
21 {
22     vector<Person> personArray;
23  
24     Person p1;
25     p1.age = 10;
26     p1.name = "小明";
27  
28     Person p2;
29     p2.age = 30;
30     p2.name = "王亮";
31  
32     Person p3;
33     p3.age = 12;
34     p3.name = "小丽";
35  
36     Person p4;
37     p4.age = 9;
38     p4.name = "小华";
39  
40     personArray.push_back(p1);
41     personArray.push_back(p2);
42     personArray.push_back(p3);
43     personArray.push_back(p4);
44  
45     vector<PersonPtr> personItArray;
46     for(auto it = personArray.begin(); it != personArray.end(); ++it)
47     {
48         personItArray.push_back(it);
49     }
50     std::stable_sort(personItArray.begin(), personItArray.end(), [](PersonPtr a, PersonPtr b){return a->age < b->age;});
51     
52     //在后面处理中又插入了一个新的person
53     Person p5;
54     p5.name = "李雷";
55     p5.age = 15;
56     personArray.push_back(p5);
57  
58     cout << personArray.capacity() << endl;
59     for(auto personPtr : personItArray)
60     {
61         cout << "name:" << personPtr->name << ", age:" << personPtr->age << endl;
62     }
63     return 0;
64 }

运行结果, 程序core掉:

 

问题原因:

4个元素的时候,vector内部处于需要renew的边界,当再插入1个的时候,出发了renew,之前的迭代器数组中插入的迭代器指向了错误的地址

解决方式:

尽量避免使用非临时场景的vector迭代器、指针,如果必须要使用,确保vector不会再次renew而导致指向错误内存

可以根据需要提前reserve一个足够的空间, 中前面问题代码中增加 reserve:

Person p4;
p4.age = 9;
p4.name = "小华";

personArray.reserve(20); //提前reserve足够空间
personArray.push_back(p1);

得到正确结果:

 

posted @ 2022-06-26 21:13  飞天赤狐  阅读(48)  评论(0)    收藏  举报