【问题标题】:Vector Iterators Incompatible向量迭代器不兼容
【发布时间】:2012-01-15 08:04:45
【问题描述】:

我有一个带有 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;
}

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

【问题讨论】:

  • 你正在返回一个向量的副本,可能你想返回一个const std::vector&lt;int&gt;&amp;
  • 您真的要返回您的向量的副本吗?
  • 请不要从函数返回 const 值,因为它会抑制 C++11 移动语义。
  • @TomalakGeret'kal 我认为标题中提到了错误。
  • @Seth:我从来没有见过一个错误,它本身就是“向量迭代器不兼容”

标签: c++ stl vector


【解决方案1】:

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

一些解决方案:

返回对std::vector&lt;int&gt; 的常量引用:

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;
}

如果不是using namespace std;,也可以 +1

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      您正在返回向量的副本。因为您是按值返回 - 您对 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())
      {
      //
      }
      

      【讨论】:

        【解决方案4】:

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

        改变这个:

        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 的成员方法中。通常不应该让类之外的东西对类的内部数据进行操作。
        • 它是一个 不同 容器的无效迭代器。两个问题。
        【解决方案5】:

        改变

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

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

        【讨论】:

          【解决方案6】:

          您的 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();
          

          【讨论】:

            【解决方案7】:

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

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

            【讨论】:

              【解决方案8】:

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

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

              【讨论】:

                【解决方案9】:

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

                v.erase(i),然后比较i != v.end(),擦除无效i,所以不能用于比较。

                【讨论】:

                  【解决方案10】:

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

                  【讨论】:

                  • 嗨,欢迎来到 Stack Overflow。您的答案虽然可能是正确的,但非常简洁且难以理解。如果您可以扩展它,那将很有用;例如,如果您包含一些使用您推荐的更改的代码?
                  • 这个确切的答案也被用于响应一个自删除的马尔可夫生成的废话问题,并被选为该废话问题的答案。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-12-20
                  • 2012-04-17
                  相关资源
                  最近更新 更多