# Effective STL Item 43：优先使用STL泛型算法以取代手写循环

STL泛型算法vs.手写的循环<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Scott Meyers

-------------------------------------------------------------------------------

[这篇文章源自一本即将出版的书。S. Meyers，Effective STL:50 Specific Ways to Improve Your Use of the Standard Template Library，改自Item 26-28（WQ注，CUJ上原文如此，应为Item 43）。 2001 Addison-Wesley。 发行：permission of Pearson Education, Inc]

class Widget {

public:

...

void redraw() const;

...

};

list<Widget> lw;

...

for (list<Widget>::iterator i =

lw.begin();

i != lw.end(); ++i) {

i->redraw();

}

for_each(lw.begin(), lw.end(),

mem_fun_ref(&Widget::redraw));

l         效率：泛型算法通常比循环高效。

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

l         可维护性: 与相应的显式循环相比，泛型算法通常使代码更干净、更直观。

for (list<Widget>::iterator i =

lw.begin();

i != lw.end();

++i) {

i->redraw();

}

// this call evaluates lw.end() exactly

// once

for_each(lw.begin(), lw.end(),

mem_fun_ref(&Widget::redraw));

// C API: this function takes a pointer

// to an array of at most arraySize

// doubles and writes data to it. It

// returns the number of doubles written.

size_t fillArray(double *pArray, size_t arraySize);

// create local array of max possible size

double data[maxNumDoubles];

// create deque, put data into it

deque<double> d;

...

// get array data from API

size_t numDoubles =

fillArray(data, maxNumDoubles);

// for each i in data, insert data[i]+41

// at the front of d; this code has a bug!

for (size_t i = 0; i < numDoubles; ++i) {

d.insert(d.begin(), data[i] + 41);

}

// remember d’s begin iterator

deque<double>::iterator insertLocation = d.begin();

// insert data[i]+41 at insertLocation, then

// increment insertLocation; this code is also buggy!

for (size_t i = 0; i < numDoubles; ++i) {

d.insert(insertLocation++, data[i] + 41);

}

deque<double>::iterator insertLocation =

d.begin();

// update insertLocation each time

// insert is called to keep the iterator valid,

// then increment it

for (size_t i = 0; i < numDoubles; ++i) {

insertLocation =

d.insert(insertLocation, data[i] + 41);

++insertLocation;

}

// copy all elements from data to the

// front of d, adding 41 to each

transform(data, data + numDoubles,

inserter(d, d.begin()),

bind2nd(plus<int>(), 41));

vector<int> v;

int x, y;

...

// iterate from v.begin() until an

// appropriate value is found or

// v.end() is reached

vector<int>::iterator i = v.begin();

for( ; i != v.end(); ++i) {

if (*i > x && *i < y) break;

}

// i now points to the value

// or is the same as v.end()

// find the first value val where the

// "and" of val > x and val < y is true

vector<int> iterator i =

find_if(v.begin(), v.end(),

compose2(logical_and<bool>(),

bind2nd(greater<int>(), x),

bind2nd(less<int>(), y)));

find_if()的调用可以不显得那么复杂，只要将测试的逻辑封装入一个独立的functor(也就是申明了operator()成员函数的类)：

template<typename T>

class BetweenValues:

public std::unary_function<T, bool> {

public:

// have the ctor save the

// values to be between

BetweenValues(const T& lowValue,

const T& highValue)

: lowVal(lowValue), highVal(highValue)

{}

// return whether val is

// between the saved values

bool operator()(const T& val) const

{

return val > lowVal && val < highVal;

}

private:

T lowVal;

T highVal;

};

...

vector<int> iterator i =

find_if(v.begin(), v.end(),

BetweenValues<int>(x, y));

// beginning of function

{

...

template <typename T>

class BetweenValues:

public std::unary_function<T, bool> { ... };

vector<int>::iterator i =

find_if(v.begin(), v.end(),

BetweenValues<int>(x, y));

...

}

// end of function

// beginning of function

{

...

class BetweenValues:

public std::unary_function<int, bool> { ... };

vector<int> iterator i =

find_if(v.begin(), v.end(),

BetweenValues(x, y));

...

}

// end of function

[1] To learn more about compose2, consult the SGI STL website (<http://www.sgi.com/tech/stl/>) or Matt Austern’s book, Generic Programming and the STL (Addison-Wesley, 1999).

[2] Range member functions are container member functions such as insert, erase, and assign that take two iterators specifying a range to e.g., insert, erase, or assign. A single call to a range member is generally much more efficient than a hand-written loop that does the same thing. For details, consult Item 5 of Effective STL.

• 本文已收录于以下专栏：

## STL的一些泛型算法

• byijie
• 2012年11月03日 09:47
• 1193

## C++ Primer笔记6_STL之泛型算法

1.泛型算法： 大多数算法定义在头文件algorithm中，标准库还在头文件numeric中定义了一组数值泛型算法 举例： find函数用于找出容器中一个特定的值，有三个参数 int val = 1...
• scottly1
• 2014年06月06日 12:25
• 1311

## C++学习之标准库泛型算法_STL算法

• xhu_eternalcc
• 2014年03月22日 21:00
• 1978

## Effective STL 中文版(完整版)

Winter总算找到《Effective STL》的完整中文版了，奉献给大家。书中作者解释了怎样结合STL组件来在库的设计得到最大的好处。这样的信息允许你对简单、直接的问题开发简单、直接的解决方案，...
• WinterTree
• 2005年01月16日 01:23
• 16312

## Effective STL目录

从去年12月开始，我花了40天看了《Effective STL》这本书，并写了相关的读书笔记，我在考虑是否将这部分笔记在BLOG上贴出来。在此之前，先贴上Effective STL目录，并且强...
• hanyu1980
• 2006年06月20日 15:22
• 1166

## 一些C++ STL泛型算法整理

• yibo_ge
• 2016年04月04日 22:04
• 343

## Effective STL 中文版(完整版）

Winter总算找到《Effective STL》的完整中文版了，奉献给大家。书中作者解释了怎样结合STL组件来在库的设计得到最大的好处。这样的信息允许你对简单、直接的问题开发简单、直接的解决方案，也...
• sdnxiaotao
• 2008年07月05日 13:23
• 438

## Effective STL学习

effect stl读书笔记
• skyztttt
• 2017年02月23日 17:11
• 374

## effective stl 第19条：理解相等（equality）和等价（equivalence）的区别

#include #include #includeusing namespace std;bool ciStringCompare(const string l, const string r) {...
• u014110320
• 2016年09月20日 23:36
• 251

## 泛型算法find和find_if以及sort

• jiayichendddd
• 2015年01月08日 22:39
• 1390

举报原因： 您举报文章：Effective STL Item 43：优先使用STL泛型算法以取代手写循环 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)