R语言 intellij idea下载 比特微 自承式光缆 caching joomla request rss 河南普通话 less使用 mysql重新初始化 增删改查sql语句 bootstrap单选按钮 python转java 车载u盘 python中index的用法 python输出中文 java语法基础 java对象和类 java获取ip地址 java中接口的定义 java声明变量 java线程死锁 java的特性 java的多线程 linuxsudo命令 p2pover Ext2Fsd ps选择反向快捷键 选项卡 千千静听老版本 一羽月土米水日古余打一成语 js关闭当前页面 ps调整边缘抠头发丝 r330不能识别墨盒 彻底卸载mysql 透视网格工具怎么取消 加速软件 勇敢者的游戏3 bin文件编辑器
当前位置: 首页 > 学习教程  > 编程语言

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

2020/8/31 14:36:57 文章标签:

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;
}

本文链接: http://www.dtmao.cc/news_show_150262.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?