简体   繁体   English

矢量迭代器不兼容

[英]Vector Iterators Incompatible

I have a class with a std::vector data member eg 我有一个带有std :: vector数据成员的类,例如

class foo{
public:

const std::vector<int> getVec(){return myVec;} //other stuff omitted

private:
std::vector<int> myVec;

};

Now at some part of my main code I am trying to iterate through the vector like this: 现在在我的主要代码的某些部分,我试图迭代这样的向量:

std::vector<int>::const_iterator i = myFoo.getVec().begin();
while( i != myFoo.getVec().end())
{
   //do stuff
   ++i;
}

The moment I reach this loop, I get the aforementioned error. 我到达这个循环的那一刻,我得到了上述错误。

The reason you are getting this, is that the iterators are from two (or more) different copies of myVec. 你得到这个的原因是,迭代器来自myVec的两个(或更多)不同的副本。 You are returning a copy of the vector with each call to myFoo.getVec() . 每次调用myFoo.getVec() ,都会返回向量的副本。 So the iterators are incompatible . 所以迭代器是不兼容的

Some solutions: 一些解决方案

Return a const reference to the std::vector<int> : 返回对std::vector<int>的const引用:

const std::vector<int> & getVec(){return myVec;} //other stuff omitted

Another solution, probably preferable would be to get a local copy of the vector and use this to get your iterators: 另一个解决方案,可能更可取的是获取向量的本地副本并使用它来获取迭代器:

const std::vector<int> myCopy = myFoo.getVec();
std::vector<int>::const_iterator i = myCopy.begin();
while(i != myCopy.end())
{
  //do stuff
  ++i;
}

Also +1 for not using namespace std; 另外+1表示不using namespace std;

You are returning a copy of the vector. 您正在返回该向量的副本。 Because you are returning by value - your call to begin() and end() are for completely different vectors. 因为您按值返回 - 您对begin()和end()的调用是针对完全不同的向量。 You need to return a const & to it. 你需要返回一个const&它。

const std::vector<int> &getVec(){return myVec;}

I would do this slightly differently though. 我会这样做略有不同。 I'd make the class act a little like a standard container 我让这个课程有点像标准容器

class Data
{
   public:
      typedef std::vector<int>::const_iterator const_iterator;

      const_iterator begin() const { return myVec.begin(); }
      const_iterator end() const { return myVec.end(); }
};

Data::const_iterator i=myFoo.begin();

while(i != myFoo.end())
{
//
}

Another cause of the MSVC STL debug assertion "vector iterators incompatible" is operating on an invalidated iterator. MSVC STL调试断言“矢量迭代器不兼容”的另一个原因是在无效的迭代器上运行。

Ie v.erase(i) , and then compare i != v.end() the erase invalidates i and so it cannot be used in a comparison. v.erase(i) ,然后比较i != v.end()擦除使i无效,因此它不能用于比较。

well, I don't think vector copy could be the only cause, that seems to be too obivious to me. 好吧,我不认为矢量副本可能是唯一的原因,这对我来说似乎过于苛刻。

in my case I just find that corrupted stack, heap, uninteneded changes could also result in this failure, and it will in fact hiding the underlying reason. 在我的情况下,我只是发现损坏的堆栈,堆,无条件的更改也可能导致此失败,并且实际上隐藏了潜在的原因。 in my case, I changed to use indexer to iterate through and find the root cause. 在我的情况下,我改为使用索引器迭代并找到根本原因。

Another reason why this assert can trigger is if you would allocate "foo" with 'malloc' instead of 'new', effectively skipping the constructor(s). 这个断言可以触发的另一个原因是你是否将“foo”分配给'malloc'而不是'new',从而有效地跳过了构造函数。

It's unlikely to happen to a project developed from scratch in C++, but when converting plain-C code to C++ (replacing a static array[] in some struct with an stl-vector) you might just not realise that dynamic instances of said struct (and the members inside) are not going to have their constructor called - unless you also change 'malloc' to 'new'. 在C ++中从头开发的项目不太可能发生,但是当将普通C代码转换为C ++(用某个stl-vector替换某个结构中的静态数组[])时,您可能根本没有意识到所述结构的动态实例(并且其中的成员不会被调用它们的构造函数 - 除非你也将'malloc'改为'new'。

The problem is that you always return another copy of the vector. 问题是你总是返回另一个向量的副本。 Use a reference: 使用参考:

const std::vector<int>& getVec(){return myVec;} //other stuff omitted

You are making a constant copy of the member vector, not accessing the member vector. 您正在创建成员向量的常量副本,而不是访问成员向量。

Change this: 改变这个:

const std::vector<int> getVec(){return myVec;} //other stuff omitted

to this: 对此:

const std::vector<int> & getVec(){return myVec;} //other stuff omitted

To go a little deeper, the iterator you get from this statement: 更深入一点,你从这个声明得到的迭代器:

std::vector<int>::const_iterator i = myFoo.getVec().begin();

is an iterator to the temporary copy of your vector, which goes away after that statement executes, invalidating the iterator. 是向量的临时副本的迭代器,它在该语句执行后消失,使迭代器无效。

Change 更改

const std::vector<int> getVec(){return myVec;}

to

const std::vector<int>& getVec(){return myVec;}

Your getVec() function returns a deep copy of the member vector, so the two getVec() calls you make to retrieve iterators get iterators to different containers. 你的getVec()函数返回成员向量的深层副本,因此你要做的两个getVec()调用来检索迭代器获取不同容器的迭代器。 That is, you can't reach getVec().end() from a separate getVec().begin() iterator without invoking undefined behavior. 也就是说,您无法从单独的getVec()。begin()迭代器到达getVec()。end()而不调用未定义的行为。

You can solve this in two ways: 您可以通过两种方式解决此问题:

1) Have getVec return a const reference (that is, const std::vector&) (preferred) or... 1)让getVec返回一个const引用(即const std :: vector&)(首选)或......

2) Replace the two getVec() calls with one and save the result to a std::vector variable. 2)用一个替换两个getVec()调用,并将结果保存到std :: vector变量。 Then, use that variable for both calls to begin() and end(). 然后,将该变量用于begin()和end()两个调用。 Eg: 例如:

std::vector<int> v = myFoo.getVec();
std::vector<int>::const_iterator b = v.begin();
std::vector<int>::const_iterator e = v.end();

Because you are returning by value - your call to begin() and end() are for completely different vectors. 因为您按值返回 - 您对begin()和end()的调用是针对完全不同的向量。 You need to return a const & to it 你需要返回一个const&它

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

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