C++ 向量迭代器不兼容

C++ 向量迭代器不兼容,c++,stl,vector,C++,Stl,Vector,我有一个带有std::vector数据成员的类,例如 class foo{ public: const std::vector<int> getVec(){return myVec;} //other stuff omitted private: std::vector<int> myVec; }; class-foo{ 公众: const std::vector getVec(){return myVec;}//省略了其他内容 私人: std::载体myVec;

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

class foo{
public:

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

private:
std::vector<int> myVec;

};
class-foo{
公众:
const std::vector getVec(){return myVec;}//省略了其他内容
私人:
std::载体myVec;
};
现在,在我的主代码的某些部分,我尝试像这样迭代向量:

std::vector<int>::const_iterator i = myFoo.getVec().begin();
while( i != myFoo.getVec().end())
{
   //do stuff
   ++i;
}
std::vector::const_迭代器i=myFoo.getVec().begin();
而(i!=myFoo.getVec().end())
{
//做事
++一,;
}

当我到达这个循环时,我得到了前面提到的错误。

之所以得到这个错误,是因为迭代器来自myVec的两个(或更多)不同副本。每次调用
myFoo.getVec()
,都会返回向量的副本。因此迭代器是不兼容的

一些解决方案:

返回对
std::vector
的常量引用:

const std::vector&getVec(){return myVec;}//省略了其他内容
另一种解决方案可能更可取,即获取向量的本地副本,并使用此副本获取迭代器:

const std::vector<int> myCopy = myFoo.getVec();
std::vector<int>::const_iterator i = myCopy.begin();
while(i != myCopy.end())
{
  //do stuff
  ++i;
}
const std::vector myCopy=myFoo.getVec();
std::vector::const_迭代器i=myCopy.begin();
而(i!=myCopy.end())
{
//做事
++一,;
}

对于不使用命名空间std的
,也为+1

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

const std::vector<int>& getVec(){return myVec;} //other stuff omitted
const std::vector&getVec(){return myVec;}//省略了其他内容

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

const std::vector<int> &getVec(){return myVec;}
const std::vector&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())
{
//
}
类数据
{
公众:
typedef std::vector::const_迭代器const_迭代器;
常量迭代器begin()常量{return myVec.begin();}
const_迭代器end()const{return myVec.end();}
};
Data::const_迭代器i=myFoo.begin();
而(i!=myFoo.end())
{
//
}

您正在创建成员向量的恒定副本,而不是访问成员向量

更改此项:

const std::vector<int> getVec(){return myVec;} //other stuff omitted
const std::vector getVec(){return myVec;}//省略了其他内容
为此:

const std::vector<int> & getVec(){return myVec;} //other stuff omitted
const std::vector&getVec(){return myVec;}//省略了其他内容
更深入地说,您从以下语句中获得的迭代器:

std::vector<int>::const_iterator i = myFoo.getVec().begin();
std::vector::const_迭代器i=myFoo.getVec().begin();
是向量的临时副本的迭代器,执行该语句后,该副本将消失,从而使迭代器无效。

更改

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

const std::vector&getVec(){return myVec;}
您的getVec()函数返回成员向量的深度副本,因此您为检索迭代器而进行的两个getVec()调用将迭代器获取到不同的容器。也就是说,如果不调用未定义的行为,就无法从单独的getVec().begin()迭代器访问getVec().end()

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

1) 让getVec返回常量引用(即常量std::vector&)(首选)或

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

std::vector v=myFoo.getVec();
std::vector::const_迭代器b=v.begin();
std::vector::const_迭代器e=v.end();

好吧,我不认为向量拷贝是唯一的原因,这似乎太明显了


在我的例子中,我只是发现损坏的堆栈、堆和不必要的更改也可能导致此失败,并且它实际上隐藏了根本原因。在我的例子中,我改为使用indexer进行迭代并找到根本原因。

此断言可以触发的另一个原因是,如果您将“foo”分配为“malloc”而不是“new”,则实际上会跳过构造函数


不可能发生在C++中从头开始开发的项目,但是当将SULL C代码转换为C++(用STL向量替换某个结构中的静态数组)时,可能无法实现该结构的动态实例(以及内部成员)不会调用它们的构造函数-除非还将“malloc”更改为“new”。

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


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

因为您是按值返回的-对begin()和end()的调用用于完全不同的向量。您需要返回一个常量&to it

您正在返回向量的副本,可能您想要返回一个
const std::vector&
您真的想要返回向量的副本吗?请不要从函数返回常量值,因为它禁止了C++11移动语义。@TomalakGeret'kal我想这个错误在标题中已经提到了。@Seth:我从来没有看到过一个错误,它只是简单地读取“向量迭代器不兼容”这个稍微偏离主题的内容,但是你的for循环应该在foo类的成员方法中。一般来说,不应该让类外的东西对类的内部数据进行操作,它是另一个容器的无效迭代器。两个问题。嗨,欢迎来到堆栈溢出。你的答案虽然可能是正确的,但却相当简洁,难以理解。如果你能扩展它,它将是有用的;例如,如果您包含一些使用您建议的更改的代码?此确切答案也用于回答自删除马尔可夫生成的无意义问题,并选择作为所述无意义问题的答案。
const std::vector<int> getVec(){return myVec;}
const std::vector<int>& getVec(){return myVec;}
std::vector<int> v = myFoo.getVec();
std::vector<int>::const_iterator b = v.begin();
std::vector<int>::const_iterator e = v.end();