关于算法库几个函数的用法浅析

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值