简体   繁体   English

向量向量的C ++迭代器

[英]c++ iterators for vector of vectors

Why I am getting a 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];

I have a vector of vectors and vector of iterators and I am trying to insert a value in one of the sub vectors using the index of the iterator. 我有一个向量vectors和一个迭代器vector,我正在尝试使用迭代器的索引在一个子向量中插入一个值。

any idea ?? 任何想法 ??

There are two sources of undefined behavior in your program. 程序中有两种未定义行为的来源。

First , when you do this: 首先 ,当您执行此操作时:

c.push_back(j);

You are incrementing the size of the vector. 您正在增加向量的大小。 If the size of the vector exceeds its capacity, the vector has to reallocate a bigger storage to hold its current elements and its new element - that's because vectors must always store elements in a contiguous region of storage. 如果向量的大小超过其容量,则向量必须重新分配更大的存储空间以容纳其当前元素新元素-这是因为向量必须始终将元素存储在连续的存储区域中。

When reallocation occurs, iterators are invalidated. 重新分配发生时,迭代器将失效。 In particular, it is possible that your iterator citr obtained this way prior to insertions: 特别是,您的迭代器citr可能是在插入之前以这种方式获得的:

citr= c.begin();

Will be invalidated. 将无效。 Dereferencing an invalid iterator injects undefined behavior in your program. 取消引用无效的迭代器会在程序中注入未定义的行为。

Second , when you do this: 其次 ,当您执行此操作时:

cellitr.push_back(citr);

You are storing an iterator to a vector ( c ) that will go out of scope when the loop exits - that will make the stored iterator an invalid iterator. 您正在将迭代器存储到向量( c ),该向量将在循环退出时超出范围-这将使存储的迭代器成为无效的迭代器。 Again, dereferencing an invalid iterator will give you undefined behavior. 再次,取消引用无效的迭代器将给您未定义的行为。


In order to avoid both sources of undefined behavior, you could change your loop as follows: 为了避免两种未定义行为的来源,您可以按以下方式更改循环:

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());
}

Notice, that in C++11 you could avoid the inner loop and make the above more compact: 注意,在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());
}

Here, a copy of c is pushed into cells : 在这里, c副本被推入cells

cells.push_back(c);

Here, you store an iterator to a local vector c , whose lifetime is only one single iteration of the for-loop: 在这里,您将迭代器存储到本地向量c ,该向量的生存期仅为for循环的单次迭代:

cellitr.push_back(citr);

You are storing iterators to local vectors, and trying to access them in a scope where these vectors do not exist. 您正在将迭代器存储到本地向量,并尝试在不存在这些向量的范围内访问它们。

Besides this, there may be some iterator invalidation issues due to the growth of c . 除此之外,由于c的增长,可能存在一些迭代器失效问题。 This can be fixed via a call to c.reserve(10) , but you have to fix the other problem first: 这可以通过调用c.reserve(10)来解决,但是您必须首先解决另一个问题:

std::vector<int> c;
....
cellitr.push_back(cells.back().begin());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM