向量矢量的c ++迭代器

Ahm*_*ato 1 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];
Run Code Online (Sandbox Code Playgroud)

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

任何的想法 ??

And*_*owl 5

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

首先,当你这样做:

c.push_back(j);
Run Code Online (Sandbox Code Playgroud)

您正在递增矢量的大小.如果载体的大小超过它的容量时,载体具有重新分配一个更大的存储空间来保存其当前元素它的新的元素-这是因为载体必须总是存储在存储器的连续区域的元件.

重新分配时,迭代器无效.特别是,您的迭代器可能citr在插入之前以这种方式获得:

citr= c.begin();
Run Code Online (Sandbox Code Playgroud)

将失效.取消引用无效的迭代器会在程序中注入未定义的行为.

其次,当你这样做时:

cellitr.push_back(citr);
Run Code Online (Sandbox Code Playgroud)

您正在将一个迭代器存储到一个vector(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());
}
Run Code Online (Sandbox Code Playgroud)

请注意,在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());
}
Run Code Online (Sandbox Code Playgroud)