📄 item_084.htm
字号:
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span>++current;<span style='mso-tab-count:
1'> </span><i style='mso-bidi-font-style:normal'>//
…</i></span><i style='mso-bidi-font-style:normal'><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>然后在安全的时候递增它</span><span
lang=EN-US><o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>}</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>调用算法根本就不会遇到正确性的陷阱:</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt;tab-stops:270.0pt'><span
lang=EN-US>transform( data, data + max,<span style='mso-tab-count:1'> </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>从</span><span lang=EN-US>data</span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>复制元素</span><span
lang=EN-US><o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:36.0pt;tab-stops:270.0pt'><span
lang=EN-US><span
style='mso-spacerun:yes'>
</span>inserter(d, d.begin()),<span style='mso-tab-count:1'> </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>到</span><span lang=EN-US>d</span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的头部</span><span
lang=EN-US><o:p></o:p></span></i></p>
<p class=MsoNormal style='margin-left:36.0pt;tab-stops:270.0pt'><span
lang=EN-US><span
style='mso-spacerun:yes'>
</span>bind2nd(plus<double>(), 41) );<span style='mso-tab-count:1'> </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>每个元素加</span><span lang=EN-US>41<o:p></o:p></span></i></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>大家都知道</span><span lang=EN-US>bind2nd</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>和</span><span lang=EN-US>plus</span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>很难用。坦白地说,没人会经常使用它们,这同样是因为它们损害了可读性(参见第</span><span
lang=EN-US>6</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>条)。</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>但是</span><span lang=EN-US>lambda</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>函数会为我们生成函数对象,这使得我们只要编写下面的代码:</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US>transform( data,
data + max, inserter( d, d.begin() ), _1 + 41 );</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>示例</span><span lang=EN-US>2</span></i><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>:查找位于</span><span lang=EN-US>x</span></i><i
style='mso-bidi-font-style:normal'><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>和</span><span
lang=EN-US>y</span></i><i style='mso-bidi-font-style:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>之间的第一个元素。</span></i><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>考虑下面这个赤裸裸的循环,它在一个</span><span
lang=EN-US>vector<int> v</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>中查找第一个位于</span><span
lang=EN-US>x</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>和</span><span lang=EN-US>y</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>之间的值,并得到一个指向被找到的元素或</span><span lang=EN-US>v.end()</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>的迭代器:</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>for(
vector<int>::iterator i = v.begin(); i != v.end(); ++i )</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span><span
style='mso-spacerun:yes'> </span>if( *i > x && *i < y )
break;</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>调用算法就比较麻烦了。没有</span><span lang=EN-US>lambda</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,仅有的两种选择是编写自定义的函数对象或是使用标准的</span><span lang=EN-US>binder</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>。唉,如果选择使用</span><span lang=EN-US>binder</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,那么我们不能单独使用标准的</span><span lang=EN-US>binder</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,而是需要使用不标准的(虽然大多数</span><span lang=EN-US>STL</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>实现都提供)</span><span lang=EN-US>compose2 adapter</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,即便如此,得到的代码也难以理解,没人会真的这样写:</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>vector<int>::iterator i = find_if(
v.begin(), v.end(),</span></p>
<p class=MsoNormal><span lang=EN-US><span
style='mso-spacerun:yes'>
</span>compose2( logical_and<bool>(),</span></p>
<p class=MsoNormal><span lang=EN-US><span
style='mso-spacerun:yes'>
</span>bind2nd(greater<int>(), x),</span></p>
<p class=MsoNormal><span lang=EN-US><span
style='mso-spacerun:yes'>
</span>bind2nd(less<int>(), y) ) );</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>另一种选择,也就是编写自定义的函数对象,是可行的。它在调用点看起来也不错,它主要的缺点是需要编写一个</span><span
lang=EN-US>BetweenValues</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>函数对象,这使得代码的逻辑在视觉上远离了调用点:</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>template<typename
T></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>class
BetweenValues : public unary_function<T, bool> {</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>public:</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span>BetweenValues( const T& low, const
T& high ) : low_(low), high_(high) {}</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span>bool operator()( const T& val ) const
{return val > low_ && val < high_; }</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt;tab-stops:225.0pt'><span
lang=EN-US>private:<span style='mso-tab-count:1'> </span><i
style='mso-bidi-font-style:normal'>// </i></span><i style='mso-bidi-font-style:
normal'><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>远离了使用的地方</span></i></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><span
style='mso-spacerun:yes'> </span>T low_, high_;</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>};</span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='margin-left:36.0pt'><span lang=EN-US>vector<int>::iterator
i = find_if( v.begin(), v.end(), BetweenValues<int>(x, y) );</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>Lambda</span><span style='font-family:宋体;
mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>函数会为我们生成函数对象,这使得我们只要编写下面的代码:</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal style='text-indent:36.0pt'><span lang=EN-US>vector<int>::iterator
i = find_if( v.begin(), v.end(), _1 > x && _1 < y );</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><b style='mso-bidi-font-weight:normal'><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>例外</span></b></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>在和函数对象一起使用时,调用算法使得循环体远离了调用发生的地方,这可能会使循环更难以阅读。(把简单的函数对象和标准的以及不标准的</span><span
lang=EN-US>binder</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>拼凑到一起不是一个现实的选择。)</span></p>
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
<p class=MsoNormal><span lang=EN-US>[Boost] </span><span style='font-family:
宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的</span><span
lang=EN-US>lambda</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>库提供的函数解决了这两个问题,能在当今的编译器上工作,也很可靠,但它们无法在较老的编译器上工作,如果编写得不正确,还会产生悔涩的错误信息。另外,如果要调用具名函数,包括成员函数,那么仍然需要类似于</span><span
lang=EN-US>binder</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>的语法。</span></p>
</div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -