C++迭代器调用类中链表getter时触发段错误的原因
问题分析:为什么第一次迭代触发段错误?
#include <iostream> #include <list> using namespace std; class A{ private: list<int*> data; public: A(list<int*> data_){data=data_;} list<int*> getData(){return data;} }; int main(){ list<int*> temp; temp.push_back(new int(1)); temp.push_back(new int(2)); temp.push_back(new int(3)); temp.push_back(new int(4)); A a(temp); // First Iteration list<int*>::iterator it; cout<<(a.getData()).size()<<endl; for (it = (a.getData()).begin(); it != (a.getData()).end(); it++) cout << *(*it) << endl; // Second Iteration list<int*> mylist = a.getData(); for (it = mylist.begin(); it != mylist.end(); it++) cout << *(*it) << endl; }
上述代码中,第一次迭代会触发segmentation fault(段错误),但第二次迭代不会,请问第一次迭代出现段错误的原因是什么?
原因解析
核心问题出在getData()的返回值性质上:
list<int*> getData()的返回类型是list的副本,而非原对象的引用。- 第一次迭代时,
(a.getData())每次调用都会生成一个临时的list对象。当执行it = (a.getData()).begin()这条语句后,这个临时对象会立即被销毁,此时it就变成了悬空迭代器——指向一块已经被释放的内存空间。后续循环中通过这个迭代器访问元素,直接触发了内存访问错误,也就是段错误。 - 第二次迭代时,我们把
getData()返回的副本赋值给了局部变量mylist,mylist的生命周期覆盖了整个循环过程。迭代器指向的是mylist这个有效存在的list,因此访问元素不会出现问题。
如果要避免这类问题,可以把getData()的返回类型修改为const list<int*>&(返回原对象的常量引用),这样就不会生成副本,迭代器也能指向有效内存。
内容的提问来源于stack exchange,提问作者Asher Mai
相关产品推荐
相关产品推荐

