向量迭代器不兼容

问题描述 投票:0回答:10

我有一个带有 std::vector 数据成员的类,例如

class foo{
public:

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

private:
std::vector<int> myVec;

};

现在,在我的主代码的某些部分,我尝试像这样迭代向量:

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

当我到达这个循环时,我收到了上述错误。

c++ stl vector
10个回答
77
投票

您收到此消息的原因是迭代器来自 myVec 的两个(或更多)不同副本。每次调用

myFoo.getVec()
时都会返回向量的副本。所以迭代器不兼容

一些解决方案:

返回对

std::vector<int>
的 const 引用:

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

另一种解决方案,可能更好的是获取向量的本地副本并使用它来获取迭代器:

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

11
投票

您正在返回向量的副本。因为您是按值返回 - 您对 begin() 和 end() 的调用是针对完全不同的向量。你需要返回一个 const & 给它。

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

不过我的做法会略有不同。我会让这个类有点像一个标准容器

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())
{
//
}

11
投票

MSVC STL 调试断言“向量迭代器不兼容”的另一个原因是在无效的迭代器上运行。

v.erase(i)
,然后比较
i != v.end()
,擦除会使
i
无效,因此不能用于比较。


2
投票

问题是你总是返回向量的另一个副本。使用参考:

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

2
投票

嗯,我不认为矢量复制可能是唯一的原因,这对我来说似乎太明显了。

就我而言,我只是发现损坏的堆栈、堆、意外的更改也可能导致此失败,并且实际上会隐藏根本原因。就我而言,我更改为使用索引器来迭代并找到根本原因。


2
投票

此断言可以触发的另一个原因是,如果您使用“malloc”而不是“new”分配“foo”,则有效地跳过构造函数。

对于用 C++ 从头开始开发的项目来说,这种情况不太可能发生,但是当将纯 C 代码转换为 C++ 时(用 stl 向量替换某些结构中的静态数组 []),您可能只是没有意识到所述结构的动态实例(以及里面的成员)不会调用它们的构造函数 - 除非您也将“malloc”更改为“new”。


1
投票

您正在制作成员向量的常量副本,而不是访问成员向量。

更改此:

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

对此:

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

更深入一点,从这个语句中得到的迭代器:

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

是向量临时副本的迭代器,该迭代器在该语句执行后消失,使迭代器无效。


1
投票

改变

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

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

0
投票

您的 getVec() 函数返回成员向量的深层副本,因此您为检索迭代器而进行的两个 getVec() 调用将迭代器获取到不同的容器。也就是说,如果不调用未定义的行为,则无法从单独的 getVec().begin() 迭代器到达 getVec().end() 。

您可以通过两种方式解决此问题:

1) 让 getVec 返回一个 const 引用(即 const std::vector&)(首选)或...

2) 将两个 getVec() 调用替换为一个,并将结果保存到 std::vector 变量中。然后,将该变量用于对 begin() 和 end() 的调用。例如:

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

0
投票

因为您是按值返回 - 您对 begin() 和 end() 的调用是针对完全不同的向量。你需要返回一个 const & 给它

© www.soinside.com 2019 - 2024. All rights reserved.