向量矢量的c ++迭代器

时间:2013-06-16 14:04:08

标签: c++ vector segmentation-fault

为什么我会遇到分段错误?

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

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

任何想法?

2 个答案:

答案 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());