Effective STL学习笔记-条款43

来源:互联网 发布:秋冬季棉拖鞋淘宝 编辑:程序博客网 时间:2024/05/17 06:10

尽量用算法调用代替手写循环

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

使用算法可以代替我们大部分的循环工作,例如你有一个Widget的容器,想要对每个Widget调用重绘:

class Widget{public:    Widget(int value): m_value(value){}    void print()    {        cout <<"print widget :"<<m_value<<endl;    }private:    int m_value;    //value};    vector<Widget> vw =    {        Widget(1),        Widget(2),        Widget(3)    };    //其实基于范围的for循环代码以及比迭代器和原始的for循环代码优雅很多了    for(auto& widget : vw)    {        widget.print();    }

但是我们确实可以使用算法帮助我们减少一部分工作,例如for_each:

std::for_each(vw.begin(), vw.end(), mem_fn(&Widget::print));//打印输出如下print widget :1print widget :2print widget :3

事实上,本条款将证明调用算法通常比手写的循环更优越。
为什么?有三个理由:
● 效率:算法通常比程序员产生的循环更高效。
● 正确性:写循环时比调用算法更容易产生错误。
● 可维护性:算法通常使代码比相应的显式循环更干净、更直观

例如给一个容器的所有的值都加上一个数值并保存到另一个容器:

你可能会这么做(或者使用迭代器)

    vector<int> vNums = {1,2,3,4,5,6};    deque<int>  dNums;    for(auto value : vNums)    {        dNums.push_back(value + 100);    }

但是使用算法我们可以这么做:

//1.std::transform(vNums.begin(), vNums.end(), std::inserter(dNums, dNums.begin()), std::bind(std::plus<int>(), _1,  100));//2.    std::transform(vNums.begin(), vNums.end(), std::inserter(dNums, dNums.begin()), [](int l)    {        return l + 40;    });

我们可以基于不同的类似于std::plus<int>(),做更多的扩展。

使用STL容器的C++精致程序中的循环比不使用STL的等价程序少多了。这是好事。只要能用高层次的术语——如insert、find和for_each,取代了低层次的词汇——如for、while和do,我们就提升了软件的抽象层次,并因此使得它更容易实现、文档化、增强和维护。

原创粉丝点击