📄 item_082.htm
字号:
@list l3
{mso-list-id:1891922128;
mso-list-template-ids:1133777540;}
@list l3:level1
{mso-level-number-format:bullet;
mso-level-text:\F0B7;
mso-level-tab-stop:36.0pt;
mso-level-number-position:left;
text-indent:-18.0pt;
mso-ansi-font-size:10.0pt;
font-family:Symbol;}
ol
{margin-bottom:0cm;}
ul
{margin-bottom:0cm;}
-->
</style>
<!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]--><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="2050"/>
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1"/>
</o:shapelayout></xml><![endif]-->
</head>
<body lang=ZH-CN link=blue vlink=purple style='tab-interval:36.0pt'>
<div class=Section1>
<h3><span lang=EN-US>82. </span><span style='font-family:宋体;mso-ascii-font-family:
Arial;mso-hansi-font-family:Arial'>使用公认的惯用法来真正地缩小容量以及真正地删除元素。</span></h3>
<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>swap trick</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>”。要真正地删除容器中的元素,请使用</span><span
lang=EN-US>erase-remove</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><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><a name=ch75index09></a><a name=ch75index08></a><a
name=ch75lev1sec2></a><span lang=EN-US><o:p></o:p></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>vector</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,</span><span lang=EN-US>string</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>,</span><span class=SpellE><span lang=EN-US>deque</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>)最终可能会具有不再需要的额外容量。虽然</span><span lang=EN-US>C++</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>标准库的容器没有提供一种切实可行的方法来去除额外的容量,但是下面的“</span><span lang=EN-US>swap
trick</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>”惯用法实际上可以用来去除下面类型为</span><span
lang=EN-US>container</span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的</span><span
lang=EN-US>c</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>container<T>(
c ).swap( c );<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>
shrink-to-fit</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></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>c</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>container<T>().swap(
c );<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><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>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>remove</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>算法并没有真正地从容器中移除元素。当然,它也不能;算法使用的只是迭代器的范围,如果不调用容器的成员函数,通常来说是</span><span
lang=EN-US>erase</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>,那么是无法真正地从容器中移除什么东西的。</span><span
lang=EN-US>remove</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>所做的一切就是移动它们的位置,把不需要被“移除”的元素移到范围的前面,然后返回一个迭代器,该迭代器正好指向最后一个不要被移除的元素的下一个。要真正地去除它们,需要在调用</span><span
lang=EN-US>remove</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>之后再调用</span><span lang=EN-US>erase</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>——即“</span><span lang=EN-US>erase-remove</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>”惯用法的由来。例如,要从容器</span><span lang=EN-US>c</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>中删除所有值为</span><span lang=EN-US>value</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 class=SpellE><span
class=GramE><span lang=EN-US>c.erase</span></span></span><span class=GramE><span
lang=EN-US>(</span></span><span lang=EN-US> remove( <span class=SpellE>c.begin</span>(),
<span class=SpellE>c.end</span>() ,value ) );</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>remove</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>或</span><span class=SpellE><span lang=EN-US>remove_if</span></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><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>shrink-to-fit</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>惯用法无法用于通过写时复制(</span><span lang=EN-US>copy-on-write</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>)来实现的</span><span class=SpellE><span lang=EN-US>std::string</span></span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>。一般来说可行的方法是调用</span><span class=SpellE><span lang=EN-US>s.reserve</span></span><span
lang=EN-US>(0)</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>,或是用范围构造函数</span><span lang=EN-US>string(<span
class=SpellE>s.begin</span>(), <span class=SpellE>s.end</span>()).swap(s);</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>来伪去除</span><span lang=EN-US>string</span><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>的额外容量。在实践中,这些方法都可以去除额外的容量。(另外,</span><span class=SpellE><span
lang=EN-US>std::string</span></span><span style='font-family:宋体;mso-ascii-font-family:
"Times New Roman";mso-hansi-font-family:"Times New Roman"'>的实现正在弃用写时复制,这已经是一个过时的优化了;参见</span><span
lang=EN-US>[Sutter02]</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 + -