删除循环中的矢量元素

问题描述:

我知道这个问题有类似的问题,但我没有设法通过他们的帮助找到我的代码的方式。我只想通过在循环内检查此元素的属性来删除/删除矢量的元素。我怎样才能做到这一点?我尝试了下面的代码,但收到错误的模糊消息:删除循环中的矢量元素

'operator ='功能在'Player'中不可用。

for (vector<Player>::iterator it = allPlayers.begin(); it != allPlayers.end(); it++) 
{ 
    if(it->getpMoney()<=0) 
     it = allPlayers.erase(it); 
    else 
     ++it; 
} 

我该怎么办?

更新:您认为vector::erase with pointer member问题属于同一问题吗?我是否需要一个赋值操作符?为什么?

+2

请注意,使用std :: remove_if可能会好很多。请参阅[this](http://lazarenko.me/2013/01/14/erasing-vector-the-smart-way/)帖子了解详情。 – 2013-01-14 15:12:34

+0

使用[this](http://stackoverflow.com/questions/347441/erasing-elements-from-a-vector)文章中描述的擦除/删除习惯用法。 – 2017-04-01 14:33:25

你不应该在for循环增量it

for (vector<Player>::iterator it=allPlayers.begin(); 
           it!=allPlayers.end(); 
           /*it++*/) <----------- I commented it. 
{ 

    if(it->getpMoney()<=0) 
     it = allPlayers.erase(it); 
    else 
     ++it; 
} 

通知注释的部分; it++在那里是不需要的,因为it在身体本身中增加了。

至于错误“‘运算符=’功能处于“播放”不可用”,它来自的erase()使用其内部使用operator=移动向量中的元素。为了使用erase(),类Player的对象必须是可分配的,这意味着您需要为Player类实现operator=

+1

我试过但我收到了同样的错误。当我删除上述循环(删除)程序编译。因此,删除/擦除存在问题。类Player的成员是指向其他对象的指针。在这种情况下他们成了什么? – arjacsoh 2011-12-25 09:43:43

+1

实际上,错误来自std :: vector.erase,它使用赋值运算符来移动元素以保持矢量的连续性。 – ronag 2011-12-25 11:52:27

+0

这个习语有没有名字? – sp2danny 2015-05-16 12:36:08

忘掉循环并使用std或boost范围algorthims。
使用Boost.Range连接LAMBDA它应该是这样的:

boost::remove_if(allPlayers, bind(&Player::getpMoney, _1)<=0); 
+3

+1。这是[要走的路](http://lazarenko.me/2013/01/14/erasing-vector-the-smart-way/)! – 2013-01-14 15:13:44

+24

-1不真诚的答案。例如,如何在不知道如何在较低层次上完成所述算法的情况下编写所述算法。不是每个人都可以生活在抽象天堂。关于为尝试学习Javascript的人回答'USE JQUERY !! 1!'有用。 – 2013-09-26 17:53:04

+1

此算法仅在您只想删除元素时才有用。想想情况,'if(condition)it = x.erase(it); else {file iammilind 2015-07-13 10:06:07

您的具体问题是,你的Player类没有赋值运算符。您必须让“玩家”可以复制或移动,才能将其从矢量中移除。这是由于该矢量需要连续,因此需要重新排列元素以填充删除元素时创建的间隙。

另外:

使用std算法

allPlayers.erase(std::remove_if(allPlayers.begin(), allPlayers.end(), [](const Player& player) 
{ 
    return player.getpMoney() <= 0; 
}), allPlayers.end()); 

或者即使你有升压简单:

boost::remove_erase_if(allPlayers, [](const Player& player) 
{ 
    return player.getpMoney() <= 0; 
}); 

见TIMW的答案,如果你没有对C++ 11的支持lambda表达式。

+0

我认为这个问题就是你提到的。然而,我已经添加了一个分配运算符作为Player&operator =(Player.h文件中的const Player & rhs);,但我仍然得到错误(带有不同的消息)。我是否最终需要一个拷贝构造函数? – arjacsoh 2011-12-25 11:52:25

+1

您还应该实现一个拷贝构造函数。如果您不发布相关错误或代码,很难说出问题所在。 – ronag 2011-12-25 11:54:22

if(allPlayers.empty() == false) { 
    for(int i = allPlayers.size() - 1; i >= 0; i--) { 
     if(allPlayers.at(i).getpMoney() <= 0) { 
      allPlayers.erase(allPlayers.begin() + i); 
     } 
    } 
} 

这是我的方法来删除向量中的元素。 这很容易理解,并不需要任何技巧。

+1

只是一个快速的评论:你可以用(!allPlayers.empty())替换(allPlayers.empty()== false)。 这是因为empty()返回一个布尔类型:如果vector为空,它将返回true。使用“not”运算符就像在说“如果vector不是空的”。只是为了美化你的代码:) – Floella 2016-10-17 13:04:17

+0

@Anarelle谢谢! – 2016-11-03 06:47:52

+0

非常好。谢谢。 – galian 2017-12-12 16:06:40

或者向后循环。

for (vector<Player>::iterator it = allPlayers.end() - 1; it != allPlayers.begin() - 1; it--) 
    if(it->getpMoney()<=0) 
     it = allPlayers.erase(it); 

C++ 11引入了一个新的函数集合,这些函数将在这里使用。

allPlayers.erase(
    std::remove_if(allPlayers.begin(), allPlayers.end(), 
     [](auto& x) {return x->getpMoney() <= 0;}), 
    allPlayers.end()); 

然后你得到的好处是不必做太多的结束元素转移。

+1

'std :: vector :: erase(iterator)'删除迭代器指向的单个元素。在你的例子中,它将尝试去除由'std :: remove_if'返回的迭代器指向的元素 - 这是一个传递端迭代器,所以这几乎肯定是不正确的(并且会导致崩溃)。它应该是:'allPlayers.erase(std :: remove_if(...),allPlayers.end())'而不是删除范围内的所有元素。 – Ellis 2018-03-07 19:42:39

+1

@Ellis更新,谢谢。 – UKMonkey 2018-03-07 20:36:12