1

为什么我遇到分段错误?

    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];

我有一个向量向量和迭代器向量,我正在尝试使用迭代器的索引在其中一个子向量中插入一个值。

任何的想法 ??

4

2 回答 2

5

您的程序中有两个未定义行为的来源。

首先,当你这样做时:

c.push_back(j);

您正在增加向量的大小。如果向量的大小超过其容量,则向量必须重新分配更大的存储空间来保存其当前元素新元素——这是因为向量必须始终将元素存储在连续的存储区域中。

当发生重新分配时,迭代器无效。特别是,您的迭代器有可能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());
}
于 2013-06-16T14:07:05.650 回答
4

在这里,一个副本c被推入cells

cells.push_back(c);

在这里,您将迭代器存储到本地 vector c,其生命周期只是 for 循环的一次迭代:

cellitr.push_back(citr);

您将迭代器存储到本地向量,并尝试在这些向量不存在的范围内访问它们。

除此之外,由于c. 这可以通过调用来c.reserve(10)解决,但您必须先解决另一个问题:

std::vector<int> c;
....
cellitr.push_back(cells.back().begin());
于 2013-06-16T14:07:17.717 回答