c++ 理解`remove_if()`的第三个参数
c++ understanding the third argument of `remove_if()`
我正在尝试理解 remove_if()
算法中的第三个参数。根据 description,如果函数 return 为真,则应将其删除。但是函数没有return一个bool
。 [](char c)
是什么语法?
remove_if()
是否真的删除了元素?如果是这样,为什么你之后会打电话给 erase()
。
std::string S("AA BB-4499--5");
auto newEnd = std::remove_if(S.begin(), S.end(), [](char c){return c == ' ' || c == '-';});
S.erase(newEnd, S.end());
What syntax is [](char c)?
在 C++11 及更高版本中是 lambda 语法。
在这种情况下,它用作谓词,remove_if
调用它来决定要删除哪些元素。
Does remove_if() actually remove the element?
不,它只是将 "removed" 元素移动到字符串的末尾,然后 returns 一个迭代器移动到第一个 "removed" 元素。随后的 erase()
实际上是从字符串中删除元素。这叫做 erase-remove idiom.
有两个版本的删除(不复制)算法。他们是
template<class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last,
const T& value);
和
template<class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predicate pred);
算法的第一个变体 "removes" 容器中满足条件 *i == value
的所有元素,其中 i
是范围 [first, last)
中的迭代器。
算法的第二个变体 "removes" 容器中满足条件 pred(*i) != false
的所有元素,其中 i
是范围 [first, last)
中的迭代器。
事实上,谓词在 if 语句中使用,其值根据上下文转换为 bool 类型。
这些算法实际上并没有删除元素。他们将它们移动到范围的末尾,return 移动 "removed" 元素后实际元素范围的结果范围的末尾。
调用成员函数 erase
导致实际删除这些元素。
考虑以下演示程序。
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto last = std::remove_if( v.begin(), v.end(), []( int x ) { return x % 2; } );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
for ( auto first = v.begin(); first != last; ++first )
{
std::cout << *first << ' ';
}
std::cout << "||| ";
for ( auto first = last; first != v.end(); ++first )
{
std::cout << *first << ' ';
}
std::cout << std::endl;
v.erase( last, v.end() );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
它的输出是
0 2 4 6 8 5 6 7 8 9
0 2 4 6 8 ||| 5 6 7 8 9
0 2 4 6 8
我正在尝试理解 remove_if()
算法中的第三个参数。根据 description,如果函数 return 为真,则应将其删除。但是函数没有return一个bool
。 [](char c)
是什么语法?
remove_if()
是否真的删除了元素?如果是这样,为什么你之后会打电话给 erase()
。
std::string S("AA BB-4499--5");
auto newEnd = std::remove_if(S.begin(), S.end(), [](char c){return c == ' ' || c == '-';});
S.erase(newEnd, S.end());
What syntax is [](char c)?
在 C++11 及更高版本中是 lambda 语法。
在这种情况下,它用作谓词,remove_if
调用它来决定要删除哪些元素。
Does remove_if() actually remove the element?
不,它只是将 "removed" 元素移动到字符串的末尾,然后 returns 一个迭代器移动到第一个 "removed" 元素。随后的 erase()
实际上是从字符串中删除元素。这叫做 erase-remove idiom.
有两个版本的删除(不复制)算法。他们是
template<class ForwardIterator, class T>
ForwardIterator remove(ForwardIterator first, ForwardIterator last,
const T& value);
和
template<class ForwardIterator, class Predicate>
ForwardIterator remove_if(ForwardIterator first, ForwardIterator last,
Predicate pred);
算法的第一个变体 "removes" 容器中满足条件 *i == value
的所有元素,其中 i
是范围 [first, last)
中的迭代器。
算法的第二个变体 "removes" 容器中满足条件 pred(*i) != false
的所有元素,其中 i
是范围 [first, last)
中的迭代器。
事实上,谓词在 if 语句中使用,其值根据上下文转换为 bool 类型。
这些算法实际上并没有删除元素。他们将它们移动到范围的末尾,return 移动 "removed" 元素后实际元素范围的结果范围的末尾。
调用成员函数 erase
导致实际删除这些元素。
考虑以下演示程序。
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto last = std::remove_if( v.begin(), v.end(), []( int x ) { return x % 2; } );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
for ( auto first = v.begin(); first != last; ++first )
{
std::cout << *first << ' ';
}
std::cout << "||| ";
for ( auto first = last; first != v.end(); ++first )
{
std::cout << *first << ' ';
}
std::cout << std::endl;
v.erase( last, v.end() );
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
它的输出是
0 2 4 6 8 5 6 7 8 9
0 2 4 6 8 ||| 5 6 7 8 9
0 2 4 6 8