C++:遍历向量的向量

Posted

技术标签:

【中文标题】C++:遍历向量的向量【英文标题】:C++: Iterating through a vector of vectors 【发布时间】:2009-11-27 21:18:27 【问题描述】:

你好!我正在做这个项目,现在我正在尝试:

    创建一些对象并将它们存储在向量中,这些向量将存储在另一个向量 V 中 遍历 V 内的向量 遍历各个向量内的对象

无论如何,我只是在网上搜索,然后遇到了 stl for_each 函数。它看起来很整洁,但我遇到了问题。我正在尝试以这种方式使用它:

for_each(V.begin(), V.end(), iterateThroughSmallVectors);

iterateThroug.... 只是对传递给它的向量执行相同操作..

现在我收到一个奇怪的“向量迭代器不兼容”运行时错误。我已经看过了,找不到任何有用的输入..

我不知道它是否有帮助,但 V 是存储在 A 类中的私有向量,它有一个访问器,我试图在 B 类中通过以​​下方式遍历它:

A->getV().begin(), A->getV().end(), etc..

有人知道发生了什么吗?

编辑:好的,所以我认为最好只发布代码,以及可能出现问题的地方......

gameState.h 中的getTiles:

vector<vector<tile*>> getTiles();

main.cpp 中的 for_each 循环:

for_each(currState->getTiles().begin(),currState->getTiles().end(), drawTiles);
.
.
void drawTiles(vector<tile*> row)

for_each(row.begin(), row.end(), dTile);

void dTile(tile *t)

t->draw();
        

创建向量:

int tp = -1;
int bCounter = 0;
int wCounter = 0;
for (int i = 0; i < 8; i++)

vector<tile*> row(8);
    for (int j = 0; j < 8; j++)
    
    tile *t = new tile(tp, (i+(SIDELENGTH/2))*SIDELENGTH,
        (j+(SIDELENGTH/2))*SIDELENGTH);
    row.push_back(t);
            tp *= -1;
    
currState->setTiles(row);
    tp *= -1;

以防万一:

void gameState::setTiles(vector<tile*> val)

    tiles.push_back(val);

现在更容易发现问题吗?我希望如此......如果你发现我可能在做任何愚蠢的事情,请告诉我,我对 C++ 有点陌生,指针和引用仍然让我感到困惑。

EDIT2:谢谢伙计们,效果很好......对于那个问题,现在看来我在创建瓷砖并将它们放在行矢量中时遇到了问题......似乎即使通过矢量创建并且正确通过,应该在其中的瓷砖不是(它们在 :

    for (int j = 0; j < 8; j++)
    
    tile *t = new tile(tp, (i+(SIDELENGTH/2))*SIDELENGTH,
        (j+(SIDELENGTH/2))*SIDELENGTH);
    row.push_back(t);
            tp *= -1;
    

循环。如果你们中的任何人对解决此问题有任何好的想法,欢迎您帮助我;)同时,我会继续努力解决它

【问题讨论】:

我认为您需要发布准确的代码,并特别标记您遇到此运行时错误的行。 【参考方案1】:

A::getV() 的原型是什么?

我只是推测,但如果 A::getV() 没有返回引用,那么它可以解释“向量迭代器不兼容”错误消息。

确实,A-&gt;getV().begin()A-&gt;getV().end() 将是两个迭代器在不同的向量上:每个 A-&gt;getV() 调用返回私有成员的不同副本。

希望这能帮助您调试问题。


编辑:看起来我的预期是正确的:在编辑您提供详细信息的问题后,我可以看到您正在定义

vector&lt;vector&lt;tile*&gt; &gt; getTiles();

因此,在以下声明中:

for_each(currState-&gt;getTiles().begin(),currState-&gt;getTiles().end(), drawTiles);

如上所述,对getTiles() 的每次调用都将返回成员向量的单独临时副本。因此,从 begin()end() 返回的迭代器来自不同的向量,因此您在运行时面临的错误消息。

另外,正如Charles in his detailed answer 所指出的,这些临时向量将在到达for_each 的函数体时被销毁。

考虑像这样通过 const 引用返回向量:

const vector&lt;vector&lt;tile*&gt; &gt;&amp; getTiles() const;

您也可以更改drawTiles 以避免更多副本:

void drawTiles(const vector&lt;tile*&gt;&amp; row)

【讨论】:

【参考方案2】:

我做的是:直接的方式

vector<vector<int> > vvi;
vector<vector<int> >::iterator vvi_iterator;
vector<int>::iterator vi_iterator;

for(vvi_terator = vvi.begin();vvi_iterator!=vvi.end();++vvi_iterator) 
    for(vi_iterator = (*vvi_iterator).begin();vi_iterator!=(*vvi_iterator).end();++vi _iterator) 
     cout<<*vi_iterator<<" ";
      

这是一个粗略的想法。我发现 for_each 方法对于执行双循环很麻烦。当你想真正对每个元素进行一些计算(比如每个元素的某种映射)时,for_each 很有用

【讨论】:

【参考方案3】:

你有几个严重的错误,但首先是一个小错误。

vector<vector<tile*>> getTiles();

在下一个标准出现之前,您需要在 &gt; 之间留一个空格。

vector< vector<tile*> > getTiles();

这个函数按值返回一个vector,这意味着它会创建一个新的vector 的副本,传递给函数中的return 语句。 (我假设这个函数声明是 curState 的任何类的实例。)

当你这样做时:

for_each(currState->getTiles().begin(),currState->getTiles().end(), drawTiles);

每次调用 getTiles 都会返回一个单独的临时向量副本。这不仅意味着 begin()end() 的迭代器来自不同的向量,而且在到达 for_each 的函数体时这些向量将被销毁。

看来你需要研究引用并通过引用传递,因为你需要了解这些才能在这些场景中正确使用std::for_each

【讨论】:

这基本上是我解释的;) @Gregory Pakosz:在我开始回答这个问题时,您还没有看到使用“真实”代码进行的编辑。也许您想窃取有关临时人员的警告(我认为这是理解的重点)和&gt;&gt;/&gt; &gt; 来回答您的问题? @Charles - 当然,就我而言,这只是一种“伟大的思想相似”的有趣感觉。我编辑了答案,以纳入您关于在达到for_each 的正文时被销毁的临时人员的详细信息;以及指向它的链接,以便人们阅读您对&gt;&gt;/&gt; &gt; 的评论。你肯定有我的投票!

以上是关于C++:遍历向量的向量的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 类中引用向量

C ++:终止遍历字符串向量的循环的最优雅方法?

在递归函数 C++ 中创建向量

使用向量的突破碰撞检测

在 C++ 向量的每个元素上调用函数

在 C++ 中重塑二维向量