⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 item_05.html

📁 制作本书的目的是为了方便大家的阅读。转载时请保持本电子书的完整性。 前言、条款2、16、21、44根据从Addison-Wesley出版社下载的开放条款翻译。条款26、27、28、45根据从Sc
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<?xml version="1.0" encoding="gb2312"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>条款5:尽量使用区间成员函数代替它们的单元素兄弟</title><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /><link href="css/all.css" rel="stylesheet" type="text/css" /><link rel="stylesheet" href="http://stl.winterxy.com/styles-site.css" type="text/css" /><link rel="alternate" type="application/rss+xml" title="RSS" href="http://stl.winterxy.com/index.rdf" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://stl.winterxy.com/rsd.xml" /></head><body><div id="banner"><h1><a href="http://stl.winterxy.com/" accesskey="1">Center of STL Study</a> </h1><span class="description">——最优秀的STL学习网站<script language="javascript" src="http://www.winterxy.com/cgi-bin/js/webstats.js"></script></span></div><h2>条款5:尽量使用区间成员函数代替它们的单元素兄弟</h2><p>快!给定两个vector,v1和v2,使v1的内容和v2的后半部分一样的最简单方式是什么?不要为“当v2有偶数个元素时才有一半”而烦恼,只要做一些合理的东西。</p><p>时间到!如果你的答案是</p><pre>v1.assign(v2.begin() + v2.size() / 2, v2.end()); </pre><p>或者其他很相似的东西,你就答对了,可以获得金质奖章。如果你的答案涉及到多于一条语句,但没有使用任何形式的循环,你接近了正确答案,但没有金质奖章。如果你的答案涉及到一个循环,你就需要花些时间来改进。如果你的答案涉及到多个循环,那好,我们只能说你真的需要这本书。</p><p>顺便说说,如果你对这个问题的答案的回答包含了“嗯?”,请高度注意,因为你将会学到一些真的有用的东西。</p><p>这个测验设计为做两件事。第一,它提供给我一个机会来提醒你assign成员函数的存在,太多的程序员没注意到这是一个很方便的方法。它对于所有标准序列容器(vector,string,deque和list)都有效。无论何时你必须完全代替一个容器的内容,你就应该想到赋值。如果你只是拷贝一个容器到另一个同类型的容器,operator=就是选择的赋值函数,但对于示范的那个例子,当你想要给一个容器完全的新数据集时,assign就可以利用,但operator=做不了。</p><p>这个测验的第二个理由是演示为什么区间成员函数优先于它们的单元素替代品。<dfn>区间成员函数</dfn>是一个像STL算法的成员函数,使用两个迭代器参数来指定元素的一个区间来进行某个操作。不用区间成员函数来解决这个条款开头的问题,你就必须写一个显式循环,可能就像这样:</p><pre>vector&lt;Widget&gt; v1, v2;		// 假设v1和v2是Widget的vectorv1.clear();for (vector&lt;Widget&gt;::const_iterator ci = v2.begin() + v2.size() / 2;		ci != v2.end();		++ci)	v1.push_back(*ci);</pre><p><a href="item_43.html">条款43</a>详细验证了为什么你应该尽量避免手写显式循环,但你不必读那个条款就能知道写这段代码比写assign的调用要做多得多的工作。就像我们将马上会看到的,循环也会造成一个效率的损失,但我们一会儿会处理的。</p><p>避免循环的一个方法是按照<a href="item_43.html">条款43</a>的建议,使用一个算法来代替:</p><pre>v1.clear();copy(v2.begin() + v2.size() / 2, v2.end(), back_inserter(v1));</pre><p>写这些仍然比写assign的调用要做更多的工作。此外,虽然在这段代码中没有表现出循环,在copy中的确存在一个循环(参见<a href="item_43.html">条款43</a>)。结果,效率损失仍然存在。我也会在下面讨论。在这里,我要离题一下来指出几乎所有目标区间是通过插入迭代器(比如,通过inserter,back_inserter或front_inserter)指定的copy的使用都可以——<em>应该</em>——通过调用区间成员函数来代替。比如这里,这个copy的调用可以用一个insert的区间版本代替:</p><pre>v1.insert(v1.end(), v2.begin() + v2.size() / 2, v2.end());</pre><p>这个输入量稍微比调用copy少,但它发生的也比说的要直接:数据插入v1。调用copy也表达了那个意思,但没那么直接。这把重点放到了错误的地方。对于发生了什么的关注点不应该是元素被拷贝,而是有新的数据加入v1。insert成员函数使这变得清晰了。copy的使用把它变得晦涩。关于东西被拷贝这个事实并没有什么好关注的,因为STL构建在东西会被拷贝的假定上。拷贝对STL来说很基本,它是本书<a href="item_03.html">条款3</a>的主题!</p><p>太多的STL程序员过度使用copy,所以我重复一遍我的建议:几乎所有目标区间被插入迭代器指定的copy的使用都可以用调用的区间成员函数的来代替。</p><p>返回我们的assign的例子,我们已经确定两个尽量使用区间成员函数代替它们的单元素兄弟的理由。</p><ul>	<li>一般来说使用区间成员函数可以输入更少的代码。</li>	<li>区间成员函数会导致代码更清晰更直接了当。</li></ul><p>简而言之,区间成员函数所产生的代码更容易写,更容易理解。不是这样吗?</p><p>唉,有些人会把这个论点看作编程风格的问题,而开发者喜欢争论风格问题几乎和喜欢争论什么是真正的编辑器一样。(虽然有很多疑问,但它的确是Emacs。)如果有一个确定区间成员函数优先于它们的单元素兄弟的更普遍赞成的标准将会很有好处。对于标准序列容器,我们有一个:效率。当处理标准序列容器时,应用单元素成员函数比完成同样目的的区间成员函数需要更多地内存分配,更频繁地拷贝对象,而且/或者造成多余操作。</p><p>比如,假设你要把一个int数组拷贝到vector前端。(数据可能首先存放在一个数组而不是vector中,因为数据来自于遗留的C API。对于混合使用STL容器和C API的问题的讨论,参见<a href="item_16.html">条款16</a>。)使用vector区间insert函数,真的微不足道:</p><pre>int data[numValues];			// 假设numValues在					// 其他地方定义vector&lt;int&gt; v;...

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -