for_each
定义于头文件 < algorithm >
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
1. 作用
按顺序应用给定的函数对象 f
到解引用范围 (first, last)
中的每个迭代器的结果
2. 参数
f
- 函数对象,要应用于解引用范围 [first, last) 中每个迭代器结果的函数
函数签名应当等价于如下者:
void fun(const Type &a);
签名不必拥有 const & 。类型 Type'
必须使得 InputIt
类型对象能在解引用后隐式转换到 Type
3. 返回值
f
(C++11 前)std::move(f)
(C++11 起)
4. 源码实现
// for_each. Apply a function to every element of a range.
// 对一个范围的每个元素应用一个函数。
template <class _InputIter, class _Function>
_Function for_each(_InputIter __first, _InputIter __last, _Function __f) {
__STL_REQUIRES(_InputIter, _InputIterator);
for ( ; __first != __last; ++__first)
__f(*__first);
return __f;
}
5. 使用实例
void print(int num)
{
cout << num << endl;
}
void test()
{
vector<int> nums{1, 7, 8, 0, 4, 11};
//函数对象
for_each(nums.begin(), nums.end(), print);
//Lambda表达式,也叫匿名函数
for_each(nums.begin(), nums.end(),
[](int num){cout << num << endl;});
}
for_each要求的是一个一元函数,对返回值没有要求,所以如下是没有影响的
int printRe(int num)
{
cout << num << endl;
return num;
}
bool printRe2(int num)
{
cout << num << endl;
return false;
}
void test2()
{
vector<int> nums{1, 7, 8, 0, 4, 11};
for_each(nums.begin(), nums.end(), printRe);
for_each(nums.begin(), nums.end(), printRe2);
}
remove
定义于头文件 < algorithm >
template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
1. 作用
从范围 [first, last) 移除所有满足特定判别标准的元素,并返回范围新结尾的尾后迭代器。
( 移除所有等于 value 的元素,用 operator== 比较它们 )
2. 参数
value
- 要移除的元素值
3. 返回值
新值范围的尾后迭代器(若它不是 end ,则它指向未指定值,而此迭代器与 end 之间的迭代器所指向的任何值亦然)。
4. 源码实现
template< class ForwardIt, class T >
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value)
{
first = std::find(first, last, value);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!(*i == value))
*first++ = std::move(*i);
return first;
}
这些算法并不从容器中删除元素,而是将所有不符合删除条件的元素移动到范围的前面,保持元素的相对顺序。这是在数据范围的一次传递中完成的。由于没有实际删除的元素,而容器保持相同的大小,数组尾部的长度等于“删除”项的数量;这些项保留在内存中,但处于未指定的状态。
remove返回一个迭代器,该迭代器指向第一个尾部元素,这样就可以使用一个擦除调用来删除它们。
【摘自维基百科 Erase–remove idiom】
就有如下用法:
4. 使用实例
// error example
// remove方法在遍历元素的过程中,如果直接删除元素,有可能会造成迭代器失效的问题
void test()
{
vector<int> nums{9, 6, 7, 3, 1, 8, 10, 1};
remove(nums.begin(), nums.end(), 1);
for(auto & num : nums)
{
cout << num << " ";
}
cout << endl;
}
//使用 Erase–remove 方法就可以避免之前的问题
void test2()
{
vector<int> nums{9, 6, 7, 3, 1, 8, 10, 1};
nums.erase(remove(nums.begin(), nums.end(), 1), nums.end());
for(auto & num : nums)
{
cout << num << " ";
}
cout << endl;
//使用copy复制元素内容到输出迭代器,同打印
std::copy(nums.begin(), nums.end(),
ostream_iterator<int>(cout, " "));
cout << endl;
}
replace
定义于头文件 < algorithm >
// 1)
template< class ForwardIt, class T >
void replace( ForwardIt first, ForwardIt last,
const T& old_value, const T& new_value );
// 2)
template< class ForwardIt, class UnaryPredicate, class T >
void replace_if( ForwardIt first, ForwardIt last,
UnaryPredicate p, const T& new_value );
1. 作用
以 new_value 替换范围 [first, last) 中所有满足特定判别标准的元素。
(1) 替换所有等于 old_value 的元素。
(2) 仅复制谓词 pred 对其返回 true 的元素。保持被复制元素的相对顺序。若源与目标范围重叠则行为未定义。
2. 参数
value
- 要移除的元素值
3. 返回值
新值范围的尾后迭代器(若它不是 end ,则它指向未指定值,而此迭代器与 end 之间的迭代器所指向的任何值亦然)。
4. 源码实现
template< class ForwardIt, class T >
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value)
{
first = std::find(first, last, value);
if (first != last)
for(ForwardIt i = first; ++i != last; )
if (!(*i == value))
*first++ = std::move(*i);
return first;
}
这些算法并不从容器中删除元素,而是将所有不符合删除条件的元素移动到范围的前面,保持元素的相对顺序。这是在数据范围的一次传递中完成的。由于没有实际删除的元素,而容器保持相同的大小,数组尾部的长度等于“删除”项的数量;这些项保留在内存中,但处于未指定的状态。
remove返回一个迭代器,该迭代器指向第一个尾部元素,这样就可以使用一个擦除调用来删除它们。
【摘自维基百科 Erase–remove idiom】
就有如下用法:
4. 使用实例
// error example
// remove方法在遍历元素的过程中,如果直接删除元素,有可能会造成迭代器失效的问题
void test()
{
vector<int> nums{9, 6, 7, 3, 1, 8, 10, 1};
remove(nums.begin(), nums.end(), 1);
for(auto & num : nums)
{
cout << num << " ";
}
cout << endl;
}
//使用 Erase–remove 方法就可以避免之前的问题
void test2()
{
vector<int> nums{9, 6, 7, 3, 1, 8, 10, 1};
nums.erase(remove(nums.begin(), nums.end(), 1), nums.end());
for(auto & num : nums)
{
cout << num << " ";
}
cout << endl;
//使用copy复制元素内容到输出迭代器,同打印
std::copy(nums.begin(), nums.end(),
ostream_iterator<int>(cout, " "));
cout << endl;
}