从向量中擦除,用lambda函数和函数对象给出不同的结果。
我试图从字符串向量中删除第三个元素。对于函数对象,第3和第6元素被删除,但是对于lambda版本,代码给出了预期的结果。
我尝试了以下代码:
#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骑士当兵主教/更正结果
有人能解释一下这两种行为吗?
发布于 2013-07-27 19:38:02
您是remove_if实现的受害者,Josuttis的C++标准库详细描述了这一点。
摘要如下:
第三个和第六个元素在没有lambda版本的情况下被删除,因为remove_if在处理过程中在内部复制谓词。
它在内部使用find_if来查找应该删除的元素。稍后,该算法使用谓词的副本来使用remove_if_copy处理剩余的元素(如果有的话)。
对于lambda,当您通过引用传递参数时,remove_if内部使用的lambda对象共享相同的状态
这是remove_if的近似实现。
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);
}
}发布于 2013-07-28 00:23:07
标准定义并没有说这个函数将按照特定的顺序使用谓词,它说的是:
1要求:*的类型首先应满足MoveAssignable要求(表22)。 2效果:消除迭代器i在[第一,最后)范围内引用的所有元素,这些元素对应的条件如下:*i ==值,pred(*i) != false。 3返回:结果范围的结束。 4备注:稳定(17.6.5.7)。 复杂性:对应谓词的最后一个应用程序。 注:范围内的每个元素[ ret,最后),其中ret是返回的值,具有一个有效但未指定的状态,因为算法可以通过从最初位于该范围内的元素中移除元素来消除元素。
因此,您不应该假设谓词的使用顺序与向量元素的顺序相同。
最后,您可以简单地编写
..
s.erase(s.begin()+2);
..若要删除向量的第三个元素,请执行以下操作。
诚挚的问候
https://stackoverflow.com/questions/17901678
复制相似问题