向量迭代器不兼容
我有一个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()
时都会返回一份该载体的副本。所以迭代器是不兼容。
一些解决方案:
返回一个const参考std::vector<int>
:
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;
}
而且+1不using namespace std;
问题是你总是返回矢量的另一个副本。使用参考:
const std::vector<int>& getVec(){return myVec;} //other stuff omitted
您正在返回矢量的副本。因为你正在返回值 - 你对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())
{
//
}
您正在制作成员矢量的不断副本,而不是访问成员矢量。
更改此:
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();
是一个迭代器在语句执行后消失的矢量的临时副本,使迭代器无效。
有点偏离主题,但你的for循环做的东西应该在foo类的成员方法中。你通常不应该在班级以外的课堂上操作班级的内部数据。 –
它是一个无效的_different_容器迭代器。两个问题。 –
变化
const std::vector<int> getVec(){return myVec;}
到
const std::vector<int>& getVec(){return myVec;}
你getVec()函数返回的成员向量的深层副本,所以两个getVec()调用您对检索迭代器获取迭代器不同容器。也就是说,无法调用未定义的行为,您无法从单独的getVec()。begin()迭代器到达getVec()。end()。
您可以通过两种方式解决这个问题:
1)有无getVec返回一个const引用(也就是常量的std ::矢量&)(首选)或...
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();
看到阿德里安康沃尔的答案更好的解决方案... –
好吧,我不认为向量复制可能是唯一的原因,这似乎是对我太明显。
在我的案例中,我只是发现损坏的堆栈,堆,未加入的更改也可能导致此故障,并且实际上将隐藏其根本原因。在我的情况下,我改变了使用索引器遍历并找到根本原因。
此断言触发的另一个原因是,如果您将“malloc”而不是“new”分配给“foo”,从而有效地跳过构造函数。
这不太可能发生在C++中从头开发的项目,但是当将纯C代码转换为C++(用stl-vector替换某个结构中的静态数组[]时),您可能只是没有意识到动态实例所有结构体(和里面的成员)都不会调用它的构造函数 - 除非你也将'malloc'改为'new'。
MSVC STL调试断言“向量迭代器不兼容”的另一个原因是对无效的迭代器进行操作。
I.e. v.erase(i)
,然后比较i != v.end()
擦除无效i
,所以它不能用于比较。
因为你正在返回值 - 你对begin()和end()的调用是完全不同的向量。你需要返回一个const &它
嗨,欢迎来到堆栈溢出。你的回答虽然可能是正确的,但却非常简洁明了。如果你能扩展它,这将是有用的。例如,如果您包含一些使用您推荐的更改的代码? –
这个确切的答案也用于回应自从删除马尔可夫生成的无意义问题,并被选为答复所说的无意义问题。 – user4581301
你正在返回一个向量的副本,可能你想返回一个'const std :: vector&' –
AraK
你真的想返回一个* vector * vector ? – celtschk
请不要从函数返回const值,因为它禁止C++ 11移动语义。 – ildjarn