为什么我会遇到分段错误?
std::vector<std::vector<int> > cells;
std::vector<std::vector<int>::iterator> cellitr;
for(int i=0;i<10;i++)
{
std::vector<int> c;
std::vector<int>::iterator citr;
citr= c.begin();
for(int j=0;j<10;j++)
{
c.push_back(j);
}
cells.push_back(c);
cellitr.push_back(citr);
}
qDebug()<<cells[5][6];
int *x = &cells[5][6];
cells[5].insert(cellitr[5],200);//SEG FAULT HERE
qDebug()<<cells[5][6];
我有一个向量和迭代器向量的向量,我试图使用迭代器的索引在一个子向量中插入一个值。
任何想法?
答案 0 :(得分:5)
程序中存在两种未定义行为的来源。
首先,当你这样做时:
c.push_back(j);
您正在递增矢量的大小。如果向量的大小超过其容量,则向量必须重新分配更大的存储以保持其当前元素和其新元素 - 这是因为向量必须始终将元素存储在连续的存储区域中。 / p>
重新分配时,迭代器无效。特别是,您的迭代器citr
可能在插入之前以这种方式获得:
citr= c.begin();
将失效。取消引用无效的迭代器会在程序中注入未定义的行为。
第二次,执行此操作时:
cellitr.push_back(citr);
您正在将一个迭代器存储到一个向量(c
),该向量将在循环退出时超出范围 - 这将使存储的迭代器成为无效的迭代器。同样,取消引用无效的迭代器将为您提供未定义的行为。
为了避免两种未定义行为的来源,您可以按如下方式更改循环:
cells.reserve(10);
for(int i=0;i<10;i++)
{
std::vector<int> c;
for(int j=0;j<10;j++)
{
c.push_back(j);
}
cells.push_back(c);
cellitr.push_back(cells.back().begin());
}
请注意,在C ++ 11中,您可以避免使用内部循环并使上述内容更紧凑:
#include <algorithm> // For std::iota() (C++11 only)
// ...
cells.reserve(10);
for(int i=0;i<10;i++)
{
std::vector<int> c(10);
std::iota(c.begin(), c.end(), 0);
cells.push_back(c);
cellitr.push_back(cells.back().begin());
}
答案 1 :(得分:4)
此处,c
的副本被推送到cells
:
cells.push_back(c);
在这里,您将迭代器存储到本地向量c
,其生存期只是for循环的一次迭代:
cellitr.push_back(citr);
您正在将迭代器存储到本地向量,并尝试在这些向量不存在的范围内访问它们。
除此之外,由于c
的增长,可能会出现一些迭代器失效问题。这可以通过调用c.reserve(10)
来修复,但您必须先解决其他问题:
std::vector<int> c;
....
cellitr.push_back(cells.back().begin());