• Effective_STL 学习笔记(四十三) 尽量用算法调用代替手写循环


    每一个算法接受至少一对用来指示将被操作对象区间的迭代器,比如,min_element 可以找出此区间中的最小的值,而 accumulate 则对区间内的元素作某种形式的整体求和运算,partition 将区间内的元素分割为满足和不满足某某判决条件的两个部分。算法执行时,他们进行检查指示给它的区间中的每一个元素,并且按照所期望的方式进行: 从区间中的起点循环到结束点。有一些算法,比如 find 和 find_if,可能在遍历完成前就返回了,但是即使是这些算法,内部都包含一个循环。

    算法内部是一个循环,STL 的广泛涉及面意味着,很多要用循环实现的任务,可以改用算法实现。

    1   class Widget
    2   {
    3   public:
    4     void redraw() const;
    5     . . .
    6   }

    使用循环

    1   list<Widget> lw;
    2   . . .
    3   for(list<Widget>::iterator i = lw.begin(); i != lw.end(); i++)
    4     i->redraw();

    使用 for_each 算法

    1   for_each( lw.begin(), lw.end(), mem_fun_ref(&Widget::redraw) );

    有三个理由:

      效率: 算法通常比程序员产生的循环更高效

      正确性: 写循环时比调用算法更容易产生错误

      可维护性: 算法通常使代码比相应的显示循环更干净、更直观

    效率:算法往往比循环减少了大量的函数调用次数(上例中,多次调用 lw.begin()),STL实现者知道 begin 和 end 用的很频繁,多以尽可能把他们实现得最高效,几乎肯定的是 inline 它们。实现者可以利用知道的容器具体实现优势,用库的使用者无法采用方式来优化遍历。所有STL算法使用的计算机科学都比一般的 C++ 程序员能拿的出的算法更复杂。几乎不可能被打败的 sort 及同组算法(比如,stable_sort(), nth_element()等);适用于有序区间的搜索算法(比如,binary_search, lower-bound等);就算很平凡的任务,比如从连续内存容器中除去一些对象,使用 erase-remove 惯用法都比绝大多数程序员写得更高效.

    正确性:写循环时,比麻烦的事在于确保所有使用的迭代器(a)有效,并且(b)指向所期望的地方,假设有一个数组,想获得每一个元素,把它加上41,然后将结果插入一个 deque 的前端

    1   size_t fillArray( double* pArray, size_t arraySize );//函数向数组写入数据,返回写入double个数
    2   double data[maxNumDoubles];  
    3   deque<double> d;
    4   . . .
    5   size_t numDoubles = fillArray( data, maxNumDoubles );
    6   for(size_t i = 0; i < numDoubles; i++)
    7     d.insert( d.begin(), data[i] + 41 );  // 每个数据在 d 的前端插入 data[i] + 41        
    8                               // 这段代码有一个bug!

    这可以执行,但是插入元素与在 data 中对应的元素是反序的

    不想反序可能想这样修改:

    1   deque<double>::iterator insertlocation = d.begin();  // 记下d的起始迭代器
    2   for( size_t; i < numDoubles; i++ )
    3     d.insert( insertLocation++, data[i] + 41 );// 插入data[i]+41,然后insertLocation递增
    4                                // 这段代码也有 bug

    这样使得每次调用 deque::insert 后,都导致所有指向 deque 内部的迭代器失效

    改为:

    1     deque<double>::iterator insertlocation = d.begin();
    2     for( size_t i = 0; i < numDoubles; i++ )
    3     {
    4         insertLocation = d.insert( insertLocation, data[i] + 41 );
    5       ++insertLocation;
    6     }

    调用算法 transform:

    1   transform(data, data+numDoubles, inserter(d, d.begin()), bind2nd(plus<double>(), 41));

    把迭代器扔给算法,让他们考虑操纵迭代器时的各种诡异

      

  • 相关阅读:
    解决电脑故障通用三部曲
    为什么有的人留邮箱的时候会把@写成#
    试用DreamWeaver CS6
    在CSDN上提问
    视频网站保存观看记录相关
    QQ浏览器设置无效后重新设置
    FastCopy总结
    如何在PC上多开微信
    Messager不能撤回消息
    用CSS3动画 animation实现图片旋转
  • 原文地址:https://www.cnblogs.com/kidycharon/p/10052365.html
Copyright © 2020-2023  润新知