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);
得到正确结果: