从矢量中删除,使用lambda函数和函数对象给出不同的结果。
我正在尝试从字符串向量中删除第3个元素。 使用函数对象第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 test.cpp -std = gnu ++ 0x
输入:King Queen Jack Ace Rook 骑士典当主教
输出:
S包含:King Queen Jack Ace Rook Knight Pawn Bishop
现在S包含:King Queen Ace Rook Pawn Bishop //错误的结果3和6元素被删除。
g ++ -o test test.cpp -std = gnu ++ 0x -DUSE_LAMBDA
输入:King Queen Jack Ace Rook Knight Pawn Bishop
S包含:King Queen Jack Ace Rook Knight Pawn Bishop
现在S包含:King Queen Ace Rook Knight Pawn Bishop //正确的结果
有人可以解释这两种行为吗?
答案 0 :(得分:3)
你是remove_if
实施的受害者,Josuttis的C ++标准库详细描述了这一点。
摘要是:
第3和第6个元素在没有lambda版本时被删除,因为remove_if
在处理期间在内部复制谓词。
它在内部使用find_if
来查找应该删除的元素。
稍后,该算法使用谓词的副本来处理剩余的元素(如果有的话),使用remove_if_copy
对于lambda,当您通过引用传递参数时,lambda对象在内部使用
remove_if
分享相同的州
这是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);
}
}
答案 1 :(得分:2)
标准定义并未说明此函数将按特定顺序使用谓词,它所说的是:
1要求:* first的类型应满足MoveAssignable 要求(表22)。
2效果:消除迭代器i引用的所有元素 范围[first,last)以下对应的范围 条件成立:* i == value,pred(* i)!= false。
3返回:结果范围的结束。
4备注:稳定(17.6.5.7)。
5复杂性:完全持续 - 相应的第一个应用程序 谓词。
6注意:范围[ret,last]中的每个元素,其中ret是 返回值,具有有效但未指定的状态,因为 算法可以通过从元素移动来消除元素 最初在那个范围内。
因此,您不应该假设谓词的使用顺序与矢量元素的顺序相同。
最后,你可以简单地写
..
s.erase(s.begin()+2);
..
删除矢量的第三个元素。
最好的问候