首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >矢量擦除给出意想不到的结果

矢量擦除给出意想不到的结果
EN

Stack Overflow用户
提问于 2013-07-27 19:31:36
回答 2查看 199关注 0票数 3

从向量中擦除,用lambda函数和函数对象给出不同的结果。

我试图从字符串向量中删除第三个元素。对于函数对象,第3和第6元素被删除,但是对于lambda版本,代码给出了预期的结果。

我尝试了以下代码:

代码语言:javascript
复制
#include <iostream>
#include<algorithm>
#include<iterator>
#include<vector>

using namespace std;

int main()
{

vector<string> s;

copy(istream_iterator<string>(cin),
    istream_iterator<string>(),
    back_inserter(s));

    cout<<"S contains :"<<endl;
    for(auto x:s)
        cout<<x<<" ";
    cout<<endl;

#ifndef USE_LAMBDA    

struct Word_No{
int word_ith;
int word_count;

Word_No(int x)  :word_ith(x),word_count(0){}

bool operator () (string){
return ++word_count == word_ith;
}
};
//3rd Element remove
    s.erase(remove_if(s.begin(),s.end(),Word_No(3)),s.end());
#else
    int count =0;
    s.erase(remove_if(s.begin(),
                      s.end(),
                      [&count](string){
                         return ++count ==3; //3rd Element Remove
                            }),
                      s.end());
#endif

    cout<<"Now S contains :"<<endl;
    for(auto x:s)
        cout<<x<<" ";
}

结果:

g++ -o测试test.cpp -std=gnu++0x 投入:国王皇后杰克·路克骑士典当主教 输出: S包括:国王王后杰克·鲁斯·鲁克骑士典当主教 现在S包含:国王王后Ace Rook当押主教//错误结果3和第6元素删除。 g++ -o test test.cpp -std=gnu++0x -DUSE_LAMBDA 投入:国王皇后杰克·路克骑士典当主教 S包括:国王王后杰克·鲁斯·鲁克骑士典当主教 现在S包含:国王王后Ace Rook骑士当兵主教/更正结果

有人能解释一下这两种行为吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-27 19:38:02

您是remove_if实现的受害者,Josuttis的C++标准库详细描述了这一点。

摘要如下:

第三个和第六个元素在没有lambda版本的情况下被删除,因为remove_if在处理过程中在内部复制谓词。

它在内部使用find_if来查找应该删除的元素。稍后,该算法使用谓词的副本来使用remove_if_copy处理剩余的元素(如果有的话)。

对于lambda,当您通过引用传递参数时,remove_if内部使用的lambda对象共享相同的状态

这是remove_if的近似实现。

代码语言:javascript
复制
template<typename FwdItr, typename Pred>
FwdItr std::remove_if(FwdItr b, FwdItr e, Pred f)
{
    s = find_if(b,e,f);
    if(s==e)
        return b;
    else
     {
        FwdItr temp = b;
        return remove_copy_if(++temp, e, b, f);
     }
}
票数 3
EN

Stack Overflow用户

发布于 2013-07-28 00:23:07

标准定义并没有说这个函数将按照特定的顺序使用谓词,它说的是:

1要求:*的类型首先应满足MoveAssignable要求(表22)。 2效果:消除迭代器i在[第一,最后)范围内引用的所有元素,这些元素对应的条件如下:*i ==值,pred(*i) != false。 3返回:结果范围的结束。 4备注:稳定(17.6.5.7)。 复杂性:对应谓词的最后一个应用程序。 注:范围内的每个元素[ ret,最后),其中ret是返回的值,具有一个有效但未指定的状态,因为算法可以通过从最初位于该范围内的元素中移除元素来消除元素。

因此,您不应该假设谓词的使用顺序与向量元素的顺序相同。

最后,您可以简单地编写

代码语言:javascript
复制
..
s.erase(s.begin()+2);
..

若要删除向量的第三个元素,请执行以下操作。

诚挚的问候

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17901678

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档