我有一个带有 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;
}
当我到达这个循环时,我收到了上述错误。
您收到此消息的原因是迭代器来自 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;
}
您正在返回向量的副本。因为您是按值返回 - 您对 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())
{
//
}
MSVC STL 调试断言“向量迭代器不兼容”的另一个原因是在无效的迭代器上运行。
即
v.erase(i)
,然后比较i != v.end()
,擦除会使i
无效,因此不能用于比较。
问题是你总是返回向量的另一个副本。使用参考:
const std::vector<int>& getVec(){return myVec;} //other stuff omitted
嗯,我不认为矢量复制可能是唯一的原因,这对我来说似乎太明显了。
就我而言,我只是发现损坏的堆栈、堆、意外的更改也可能导致此失败,并且实际上会隐藏根本原因。就我而言,我更改为使用索引器来迭代并找到根本原因。
此断言可以触发的另一个原因是,如果您使用“malloc”而不是“new”分配“foo”,则有效地跳过构造函数。
对于用 C++ 从头开始开发的项目来说,这种情况不太可能发生,但是当将纯 C 代码转换为 C++ 时(用 stl 向量替换某些结构中的静态数组 []),您可能只是没有意识到所述结构的动态实例(以及里面的成员)不会调用它们的构造函数 - 除非您也将“malloc”更改为“new”。
您正在制作成员向量的常量副本,而不是访问成员向量。
更改此:
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();
是向量临时副本的迭代器,该迭代器在该语句执行后消失,使迭代器无效。
改变
const std::vector<int> getVec(){return myVec;}
到
const std::vector<int>& getVec(){return myVec;}
您的 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();
因为您是按值返回 - 您对 begin() 和 end() 的调用是针对完全不同的向量。你需要返回一个 const & 给它