﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-罗朝辉（飘飘白云）</title><link>http://www.cppblog.com/kesalin/</link><description>关注：C++,3D技术,游戏开发,Window 编程</description><language>zh-cn</language><lastBuildDate>Fri, 30 Jul 2010 20:33:05 GMT</lastBuildDate><pubDate>Fri, 30 Jul 2010 20:33:05 GMT</pubDate><ttl>60</ttl><item><title>数学函数备份。。。</title><link>http://www.cppblog.com/kesalin/archive/2010/06/04/math_function.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Fri, 04 Jun 2010 10:38:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2010/06/04/math_function.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/117183.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2010/06/04/math_function.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/117183.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/117183.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 数学函数备份。。。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2010/06/04/math_function.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/117183.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2010-06-04 18:38 <a href="http://www.cppblog.com/kesalin/archive/2010/06/04/math_function.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】OpenGL 3.2规范公布 NVIDIA再次首发驱动</title><link>http://www.cppblog.com/kesalin/archive/2009/08/05/92256.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Wed, 05 Aug 2009 02:34:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/08/05/92256.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/92256.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/08/05/92256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/92256.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/92256.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: OpenGL 3.0规范发布还不到一年，3.1升级版也才四个来月，Khronos Group组织今天又对其进行了第二次升级，放出了新的3.2版本，而NVIDIA也再次紧随而至，第一家发布了相关驱动程序。OpenGL 3.2在性能增强、画质提升、几何处理加速、Direct3D程序导入简化等方面加入了大量新特性，并且和Khronos Group组织的其它标准进行了深入整合，包括用于并行计算的OpenCL、面向移动设备3D图形的OpenGL ES、创建3D web的WebGL等等。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/08/05/92256.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/92256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-08-05 10:34 <a href="http://www.cppblog.com/kesalin/archive/2009/08/05/92256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Symbian开发入门教程</title><link>http://www.cppblog.com/kesalin/archive/2009/07/09/89615.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Thu, 09 Jul 2009 03:31:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/07/09/89615.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/89615.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/07/09/89615.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/89615.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/89615.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Symbian开发入门教程: 环境配置，项目设置，图片资源，中文字符串处理等等&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/07/09/89615.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/89615.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-07-09 11:31 <a href="http://www.cppblog.com/kesalin/archive/2009/07/09/89615.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>定制任务栏托盘的 dll</title><link>http://www.cppblog.com/kesalin/archive/2009/06/08/87092.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Mon, 08 Jun 2009 12:47:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/06/08/87092.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/87092.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/06/08/87092.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/87092.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/87092.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 通过对这个 dll 进行定制（修改图标和插入菜单，很简单的替换工作），你就很容易地在新工程中使用定制的任务栏托盘，这样就省去了每写一个桌面程序就要整些桌面托盘的代码。而且这个dll所创建的任务栏托盘与主窗口是非阻塞模式的。<br><br>源文件下载： 点击这里<br>google 项目地址： http://code.google.com/p/luotasktray/<br><br>效果如图：&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/06/08/87092.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/87092.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-06-08 20:47 <a href="http://www.cppblog.com/kesalin/archive/2009/06/08/87092.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【译】VC10中的C++0x特性 part 3 : 声明之类型 </title><link>http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Sun, 07 Jun 2009 01:28:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/86960.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/86960.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/86960.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这一系列文章介绍Microsoft Visual Studio 2010 中支持的C++ 0x特性，目前有三部分。<br>Part 1 ：介绍了Lambdas， 赋予新意义的auto，以及 static_assert；<br>Part 2( 一 , 二 , 三 )：介绍了右值引用（Rvalue References）；<br>Part 3：介绍了表达式类型（decltype）<br><br>VC10中的C++0x特性 Part 1,2,3 译文打包下载（doc 和 pdf 格式）： 点此下载<br><br>本文是Part 3。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/86960.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-06-07 09:28 <a href="http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【译】VC10中的C++0x特性 Part 2 （3）：右值引用</title><link>http://www.cppblog.com/kesalin/archive/2009/06/05/86851.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Fri, 05 Jun 2009 07:09:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/06/05/86851.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/86851.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/06/05/86851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/86851.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/86851.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p style="TEXT-ALIGN: center"><span style="FONT-WEIGHT: bold">【译】VC10中的C++0x特性 Part 2 （3）：右值引用</span> <br></p>
<p style="TEXT-ALIGN: center">来源：<a title=vcvlog href="http://blogs.msdn.com/vcblog/archive/2008/10/28/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx" target=_blank>vcblog</a> 作者：Stephan T. Lavavej 翻译：<a title=飘飘白云的C++博客 href="http://www.cppblog.com/kesalin" target=_blank>飘飘白云</a> &nbsp; </p>
<p style="TEXT-ALIGN: center">(转载时请注明作者和出处。未经许可，请勿用于商业用途) <br></p>
<p>简介 </p>
<div class=postText><style>
<!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:"MS Mincho";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-alt:"ＭＳ 明朝";
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:Century;
panose-1:2 4 6 4 5 5 5 2 3 4;
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:647 0 0 0 159 0;}
@font-face
{font-family:"MS PGothic";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:536871559 0 0 0 415 0;}
@font-face
{font-family:"\@MS PGothic";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@MS Mincho";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"MS Mincho";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;
mso-fareast-language:JA;}
h1
{mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
mso-pagination:widow-orphan;
mso-outline-level:1;
font-size:24.0pt;
font-family:"MS PGothic";
mso-bidi-font-family:"MS PGothic";
mso-fareast-language:JA;}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
tab-stops:center 212.6pt right 425.2pt;
layout-grid-mode:char;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"MS Mincho";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;
mso-fareast-language:JA;}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
tab-stops:center 212.6pt right 425.2pt;
layout-grid-mode:char;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"MS Mincho";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;
mso-fareast-language:JA;}
a:link, span.MsoHyperlink
{color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{color:purple;
text-decoration:underline;
text-underline:single;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:595.3pt 841.9pt;
margin:99.25pt 3.0cm 3.0cm 3.0cm;
mso-header-margin:42.55pt;
mso-footer-margin:49.6pt;
mso-paper-source:0;
layout-grid:18.0pt;}
div.Section1
{page:Section1;}
-->
</style>
<p>这一系列文章介绍Microsoft Visual Studio 2010 中支持的C++ 0x特性，目前有三部分。 <br><a title="VC10中的C++0x特性 part 1" href="http://blog.csdn.net/kesalin/archive/2009/05/28/4222214.aspx" target=_blank>Part 1</a> ：介绍了Lambdas， 赋予新意义的auto，以及 static_assert； <br>Part 2( <a title="VC10中的C++0x特性 part 2 第一部分" href="http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html" target=_blank>一</a> , <a title="VC10中的C++0x特性 part 2 第二部分" href="http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html" target=_blank>二</a> , <a title="VC10中的C++0x特性 part 2 第三部分 " href="http://www.cppblog.com/kesalin/archive/2009/06/05/86851.html" target=_blank>三</a> )：介绍了右值引用（Rvalue References）； <br><a title="VC10中的C++0x特性 part 3" href="http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html" target=_blank>Part 3</a>：介绍了表达式类型（decltype）<br><br>VC10中的C++0x特性 Part 1,2,3 译文打包下载（doc 和 pdf 格式）： <a title="VC10中的C++0x特性（Part 1,2,3）译文doc和pdf文档" href="http://www.cppblog.com/Files/kesalin/Cplusplus0x_in_VC10.zip" target=_blank>点此下载</a></p>
</div>
<br>本文为 Part 2 的第三页
<p>&nbsp;</p>
<p>
<meta content=Word.Document name=ProgId>
<meta content="Microsoft Word 11" name=Generator>
<meta content="Microsoft Word 11" name=Originator>
<object id=ieooui classid=clsid:38481807-ca0e-42d2-bf39-b33af135cc4d></object><style>
st1\:*{behavior:url(#ieooui) }
</style><style>
<!--
/* Font Definitions */
@font-face
{font-family:"ＭＳ 明朝";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-alt:"MS Mincho";
mso-font-charset:128;
mso-generic-font-family:roman;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:SimSun;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:宋体;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:Century;
panose-1:2 4 6 4 5 5 5 2 3 4;
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:647 0 0 0 159 0;}
@font-face
{font-family:"ＭＳ Ｐゴシック";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:536871559 0 0 0 415 0;}
@font-face
{font-family:"\@ＭＳ Ｐゴシック";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:"\@SimSun";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@ＭＳ 明朝";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-charset:128;
mso-generic-font-family:roman;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0mm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"ＭＳ 明朝";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;}
h1
{mso-margin-top-alt:auto;
margin-right:0mm;
mso-margin-bottom-alt:auto;
margin-left:0mm;
mso-pagination:widow-orphan;
mso-outline-level:1;
font-size:24.0pt;
font-family:"ＭＳ Ｐゴシック";
mso-bidi-font-family:"ＭＳ Ｐゴシック";
font-weight:bold;}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{margin:0mm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
tab-stops:center 212.6pt right 425.2pt;
layout-grid-mode:char;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"ＭＳ 明朝";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{margin:0mm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
tab-stops:center 212.6pt right 425.2pt;
layout-grid-mode:char;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"ＭＳ 明朝";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;}
a:link, span.MsoHyperlink
{color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{color:purple;
text-decoration:underline;
text-underline:single;}
p
{mso-margin-top-alt:auto;
margin-right:0mm;
mso-margin-bottom-alt:auto;
margin-left:0mm;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"ＭＳ Ｐゴシック";
mso-bidi-font-family:"ＭＳ Ｐゴシック";}
span.trans
{mso-style-name:trans;}
span.apple-style-span
{mso-style-name:apple-style-span;}
span.apple-converted-space
{mso-style-name:apple-converted-space;}
p.greentitle, li.greentitle, div.greentitle
{mso-style-name:greentitle;
mso-margin-top-alt:auto;
margin-right:0mm;
mso-margin-bottom-alt:auto;
margin-left:0mm;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"ＭＳ Ｐゴシック";
mso-bidi-font-family:"ＭＳ Ｐゴシック";}
p.inner, li.inner, div.inner
{mso-style-name:inner;
mso-margin-top-alt:auto;
margin-right:0mm;
mso-margin-bottom-alt:auto;
margin-left:0mm;
mso-pagination:widow-orphan;
font-size:12.0pt;
font-family:"ＭＳ Ｐゴシック";
mso-bidi-font-family:"ＭＳ Ｐゴシック";}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:99.25pt 30.0mm 30.0mm 30.0mm;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
/* List Definitions */
@list l0
{mso-list-id:986742580;
mso-list-type:hybrid;
mso-list-template-ids:-1336744774 284093962 67698711 67698705 67698703 67698711 67698705 67698703 67698711 67698705;}
@list l0:level1
{mso-level-text:%1，;
mso-level-tab-stop:18.0pt;
mso-level-number-position:left;
margin-left:18.0pt;
text-indent:-18.0pt;
mso-fareast-font-family:"ＭＳ Ｐゴシック";}
ol
{margin-bottom:0mm;}
ul
{margin-bottom:0mm;}
-->
</style><strong>转发问题</strong><br><br>在程序员不用写高度泛化的代码的时候，C++98/03 的 lvalue， rvalue， 引用，还有模板看起来是很完美的。假设你要写一个完全泛化的函数 outer()，这个函数的目的是将任意数目个任意类型的参数传递（也就是&#8220;转发&#8221;）给函数 inner()。已有很多不错的解决方案，比如 factory 函数 make_shared&lt;T&gt;(args) 是把 args 传给 T 的构造函数，然后返回 shared_ptr&lt;T&gt;。（这样就把 T 对象和用于对它进行引用计数的代码存储到同一块动态内存中，性能上与侵入式引用计数一样好）； 而像 function&lt;Ret(args)&gt; 这样的包装类是把参数传给其内部存储的函数对象（functor），等等。在这篇文章里，我们只对 outer() 是如何把参数传递给 inner() 这部分感兴趣。至于 outer() 的返回类型是怎么决定的是另外的问题（有时候很简单，如 make_shared&lt;T&gt;(args) 总是返回 shared_prt&lt;T&gt;，），但要在完全搞定这个问题的一般化情况，你就要用到 C++0x的 decltype 特性了）。</p>
<p>&nbsp;</p>
<p>如果不带参数，就不存在这样的问题，那么带一个参数情况呢？让我们尝试写个 outer（） ：</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T&gt; void outer(T&amp; t) {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; inner(t);</strong></p>
<p><strong>}</strong></p>
<p>&nbsp;</p>
<p>问 题来了，如果传给它的参数是非常量 rvalue，那我们就无法调用 outer()。如果 inner() 接收 const int&amp; 型的参数，那 inner(5) 是可以通过编译的，但是 outer(5) 就编译不过了。因为 T 会被推导为 int， 而 int&amp; 是不能绑定到常量 5 的。</p>
<p>&nbsp;</p>
<p>好吧，让我们试试这个：</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T&gt; void outer(const T&amp; t) {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; inner(t);</strong></p>
<p><strong>}</strong></p>
<p>&nbsp;</p>
<p>如果 inner（）接收 int&amp; 型参数，那就会违法 const 正确性，编译都过不了。</p>
<p>&nbsp;</p>
<p>现在，你可以重载两个分别带 T&amp; 和 const T&amp; 参数的 outer（），这确实管用。当你调用 outer（）时，就像直接调用 inner（） 一样。</p>
<p>&nbsp;</p>
<p>可惜的是，这中方法在多参数的情况下就麻烦了（译注：要写的重载函数太多了）。你就得为每一个参数像 T1&amp; 和 const T1&amp;, T2&amp; 和 const T2&amp; 等这样进行重载，要重载的函数数目呈指数级增长。（VC9 SP1 的 tr1：：bind() 就够让人感到绝望了，它为 5 个参数这么重载出了 63 个函数。如果不这么蛮干的话，没有像这里的长篇累述，我们就很难跟使用者解释为什么不能调用用 1729 这样的 ravlue 做参数的函数。为了产生出这些重载函数使用了令人作呕的预处理机制，恶心到你都不想知道它）。</p>
<p>&nbsp;</p>
<p>在 C++98/03 中，转发问题是很严重的，而且本质上无解（必须求助于恶心的预处理机制，这会严重拖慢编译速度，还让代码变得难以阅读）。总算， rvalue 优雅地解决了这个问题。</p>
<p>&nbsp;</p>
<p><strong>完美</strong><strong>转发</strong><strong>：</strong><strong> </strong><strong>模式</strong></p>
<p>&nbsp;</p>
<p>完美转发让你能简单而清晰地只写一个模板函数就可以转发所有的参数给任意函数，不管它带几个参数，也不管参数类型是什么。而且参数的非常量/常量， lvalue/rvalue 属性都能得以保留，让你可以像使用 inner（） 一样使用 outer（），还可以和 move 语意一起用从而获得额外的好处。（ C++0x 的变长模板技术解决了&#8220;任意数目&#8221;这部分，我们在这里把 N 看做任意数目）。乍看之下很神奇，实际上很简单：</p>
<p>&nbsp;</p>
<p>C:\Temp&gt;type perfect.cpp</p>
<p>#include &lt;iostream&gt;</p>
<p>#include &lt;ostream&gt;</p>
<p>using namespace std;</p>
<p>&nbsp;</p>
<p>template &lt;typename T&gt; struct Identity {</p>
<p>&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;typename T&gt; T&amp;&amp; Forward(typename Identity&lt;T&gt;::type&amp;&amp; t) {</p>
<p>&nbsp;&nbsp;&nbsp; return t;</p>
<p>}</p>
<p>&nbsp;</p>
<p>void inner(int&amp;, int&amp;) {</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "inner(int&amp;, int&amp;)" &lt;&lt; endl;</p>
<p>}</p>
<p>&nbsp;</p>
<p>void inner(int&amp;, const int&amp;) {</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "inner(int&amp;, const int&amp;)" &lt;&lt; endl;</p>
<p>}</p>
<p>&nbsp;</p>
<p>void inner(const int&amp;, int&amp;) {</p>
<p>&nbsp; &nbsp;&nbsp;cout &lt;&lt; "inner(const int&amp;, int&amp;)" &lt;&lt; endl;</p>
<p>}</p>
<p>&nbsp;</p>
<p>void inner(const int&amp;, const int&amp;) {</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "inner(const int&amp;, const int&amp;)" &lt;&lt; endl;</p>
<p>}</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T1, typename T2&gt; void outer(T1&amp;&amp; t1, T2&amp;&amp; t2) {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; inner(Forward&lt;T1&gt;(t1), Forward&lt;T2&gt;(t2));</strong></p>
<p><strong>}</strong></p>
<p>&nbsp;</p>
<p>int main() {</p>
<p>&nbsp;&nbsp;&nbsp; int a = 1;</p>
<p>&nbsp;&nbsp;&nbsp; const int b = 2;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Directly calling inner()." &lt;&lt; endl;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; inner(a, a);</p>
<p>&nbsp;&nbsp;&nbsp; inner(b, b);</p>
<p>&nbsp;&nbsp;&nbsp; inner(3, 3);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; inner(a, b);</p>
<p>&nbsp;&nbsp;&nbsp; inner(b, a);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; inner(a, 3);</p>
<p>&nbsp;&nbsp;&nbsp; inner(3, a);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; inner(b, 3);</p>
<p>&nbsp;&nbsp;&nbsp; inner(3, b);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; endl &lt;&lt; "Calling outer()." &lt;&lt; endl;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; outer(a, a);</p>
<p>&nbsp;&nbsp;&nbsp; outer(b, b);</p>
<p>&nbsp;&nbsp;&nbsp; outer(3, 3);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; outer(a, b);</p>
<p>&nbsp;&nbsp;&nbsp; outer(b, a);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; outer(a, 3);</p>
<p>&nbsp;&nbsp;&nbsp; outer(3, a);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; outer(b, 3);</p>
<p>&nbsp;&nbsp;&nbsp; outer(3, b);</p>
<p>}</p>
<p>&nbsp;</p>
<p>C:\Temp&gt;cl /EHsc /nologo /W4 perfect.cpp</p>
<p>perfect.cpp</p>
<p>&nbsp;</p>
<p>C:\Temp&gt;perfect</p>
<p>Directly calling inner().</p>
<p>inner(int&amp;, int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>inner(int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, int&amp;)</p>
<p>inner(int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>&nbsp;</p>
<p>Calling outer().</p>
<p>inner(int&amp;, int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>inner(int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, int&amp;)</p>
<p>inner(int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>inner(const int&amp;, const int&amp;)</p>
<p>&nbsp;</p>
<p>两行！完美转发只用了两行！够简洁吧！</p>
<p>&nbsp;</p>
<p>这个例子示范了怎么把 t1 和 t2 从 outer（） 透明地转发给 inner（）； inner（） 可以知道它们的非常量/常量， lvalue/ravlue 属性，就像inner是被直接调用的那样。</p>
<p>&nbsp;</p>
<p>跟 std：：move() 一样， std::identify 和 std::forward() 都是在 C++&lt;utility&gt; 中定义的（ VC10 会有， VC10 CTP中没有）。我将演示怎么来实现它们。（再次，我将交替使用 std::identity 和我的 Identity， std::forward() 和我的 Forward()，因为他们的实现是等价的。）</p>
<p>&nbsp;</p>
<p>现在，让我们来揭开&#8220;魔术&#8220;的神秘面纱，其实它靠的就是模板参数推导和引用折叠(reference collapsing)技术。</p>
<p><strong>&nbsp;</strong></p>
<p><strong>rvalue </strong><strong>引用：模板参数推</strong><strong>导</strong><strong>和引用折叠(reference collapsing)</strong><strong></strong></p>
<p>&nbsp;</p>
<p>rvalue 引用与模板以一种特别的方式相互作用。下面是一个示例：</p>
<p>&nbsp;</p>
<p>C:\Temp&gt;type collapse.cpp</p>
<p>#include &lt;iostream&gt;</p>
<p>#include &lt;ostream&gt;</p>
<p>#include &lt;string&gt;</p>
<p>using namespace std;</p>
<p>&nbsp;</p>
<p>template &lt;typename T&gt; struct Name;</p>
<p>&nbsp;</p>
<p>template &lt;&gt; struct Name&lt;string&gt; {</p>
<p>&nbsp;&nbsp;&nbsp; static const char * get() {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "string";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;&gt; struct Name&lt;const string&gt; {</p>
<p>&nbsp;&nbsp;&nbsp; static const char * get() {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "const string";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;&gt; struct Name&lt;string&amp;&gt; {</p>
<p>&nbsp;&nbsp;&nbsp; static const char * get() {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "string&amp;";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;&gt; struct Name&lt;const string&amp;&gt; {</p>
<p>&nbsp;&nbsp;&nbsp; static const char * get() {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "const string&amp;";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;&gt; struct Name&lt;string&amp;&amp;&gt; {</p>
<p>&nbsp;&nbsp;&nbsp; static const char * get() {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "string&amp;&amp;";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;&gt; struct Name&lt;const string&amp;&amp;&gt; {</p>
<p>&nbsp;&nbsp;&nbsp; static const char * get() {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "const string&amp;&amp;";</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>template &lt;typename T&gt; void quark(T&amp;&amp; t) {</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "t: " &lt;&lt; t &lt;&lt; endl;</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "T: " &lt;&lt; Name&lt;T&gt;::get() &lt;&lt; endl;</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; "T&amp;&amp;: " &lt;&lt; Name&lt;T&amp;&amp;&gt;::get() &lt;&lt; endl;</p>
<p>&nbsp;&nbsp;&nbsp; cout &lt;&lt; endl;</p>
<p>}</p>
<p>&nbsp;</p>
<p>string strange() {</p>
<p>&nbsp;&nbsp;&nbsp; return "strange()";</p>
<p>}</p>
<p>&nbsp;</p>
<p>const string charm() {</p>
<p>&nbsp;&nbsp;&nbsp; return "charm()";</p>
<p>}</p>
<p>&nbsp;</p>
<p>int main() {</p>
<p>&nbsp;&nbsp;&nbsp; string up("up");</p>
<p>&nbsp;&nbsp;&nbsp; const string down("down");</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; quark(up);</p>
<p>&nbsp;&nbsp;&nbsp; quark(down);</p>
<p>&nbsp;&nbsp;&nbsp; quark(strange());</p>
<p>&nbsp;&nbsp;&nbsp; quark(charm());</p>
<p>}</p>
<p>&nbsp;</p>
<p>C:\Temp&gt;cl /EHsc /nologo /W4 collapse.cpp</p>
<p>collapse.cpp</p>
<p>&nbsp;</p>
<p>C:\Temp&gt;collapse</p>
<p>t: up</p>
<p>T: string&amp;</p>
<p>T&amp;&amp;: string&amp;</p>
<p>&nbsp;</p>
<p>t: down</p>
<p>T: const string&amp;</p>
<p>T&amp;&amp;: const string&amp;</p>
<p>&nbsp;</p>
<p>t: strange()</p>
<p>T: string</p>
<p>T&amp;&amp;: string&amp;&amp;</p>
<p>&nbsp;</p>
<p>t: charm()</p>
<p>T: const string</p>
<p>T&amp;&amp;: const string&amp;&amp;</p>
<p>&nbsp;</p>
<p>这里藉由 Name 的显式规格说明来打印出类型。</p>
<p>&nbsp;</p>
<p>当我们调用 quark(up) 时，会进行模板参数推导。 quark() 是一个带有模板参数 T 的模板函数，但是我们还没有为它提供显式的类型参数（比如像 quark&lt;X&gt;(up)这样的）。通过比较函数形参类型 Type&amp;&amp; 和函数实参类型（一个 string 类型的 lvalue）我们就能推导出模板实参类型。（译注：原文用 argument 表示实参，parameter 表示形参）</p>
<p>&nbsp;</p>
<p>C++0x 会转换函数实参的类型和形参的类型，然后再进行匹配。</p>
<p>&nbsp;</p>
<p>首先，转换函数实参的类型。这遵循一条<strong>特殊</strong><strong>规则</strong>(提案N2798 </p>
<p>&nbsp;</p>
<p>然后，转换函数形参的类型。不管是 C++98/03 还是 C++0x 都会解除引用( lvalue 引用和 rvalue 引用在 C++0x 中都会被解除掉)。在前面例子的四种情形中，这样我们会把 <strong>T&amp;&amp;</strong> 转换成 <strong>T</strong> 。</p>
<p>&nbsp;</p>
<p>于是， <strong>T</strong> <strong>会被推</strong><strong>导</strong><strong>成函数</strong><strong>实</strong><strong>参</strong><strong>转换</strong><strong>之后的</strong><strong>类</strong><strong>型</strong>。<strong>up</strong> 和 <strong>down</strong> 都是 lvalue，它们遵循那条特殊规则，这就是为什么 <strong>quark(up)&nbsp; </strong>打印出"<strong>T:string&amp;</strong>" ，而 <strong>quark(down)</strong> 打印出 "<strong>T: cosnt string&amp;</strong>"的原因。<strong>strange()</strong> 和 <strong>charm()</strong> 都是右值，它们遵循一般规则，这就是为什么 <strong>quark(strange())</strong> 打印出 "<strong>T: string</strong>" 而 <strong>quark(charm())</strong> 打印出"<strong>T: const string</strong>" 的原因。</p>
<p>&nbsp;</p>
<p>替换操作会在类型推导之后进行。模板形参 <strong>T</strong> 出现的每一个地方都会被替换成推导出来的模板实参类型。在 <strong>quark(string())</strong> 中 <strong>T</strong> 是 <strong>string </strong>，因此 <strong>T&amp;&amp;</strong> 会是 <strong>string&amp;&amp;</strong> 。同样，在 <strong>quark(charm())</strong> 中，<strong>T</strong> 是 <strong>const string</strong> ， 因此 <strong>T&amp;&amp;</strong> 是 <strong>const string&amp;&amp;</strong> 。但 quark(up) 和 quark(down) 不同，它们遵循另外的特殊规则。</p>
<p>&nbsp;</p>
<p>在 <strong>quark(up)</strong> 中， <strong>T</strong> 是 <strong>string&amp;</strong> 。进行替换的话 <strong>T&amp;&amp;</strong> 就成了 <strong>string&amp; &amp;&amp;</strong> ，在 C++0x 中会折叠（collapse）引用的引用，<strong>引用折叠的</strong><strong>规则</strong><strong>就是</strong><strong>&#8220;lvalue </strong><strong>引用是</strong><strong>传</strong><strong>染性的</strong><strong>&#8221;</strong>。 <strong>X&amp; &amp;</strong>, <strong>X&amp; &amp;&amp;</strong> 和 <strong>X&amp;&amp; &amp;</strong> 都会被折叠成 <strong>X&amp;</strong> ，只有 <strong>X&amp;&amp; &amp;&amp;</strong> 会被折叠成 <strong>X&amp;&amp;</strong> 。因此 <strong>string&amp; &amp;&amp;</strong> 被折叠成 <strong>string&amp;</strong> 。在模板世界里，那些看起来像 rvalue 引用的东西并不一定真的就是。 因而 <strong>quark(up)</strong> 被实例化为 <strong>quark&lt;string&amp;&gt;()</strong> ，进而 <strong>T&amp;&amp;</strong> 经替换与折叠之后变成 <strong>string&amp;</strong> 。我们可以调用 <strong>Name&lt;T&amp;&amp;&gt;::get()</strong> 来验证这个。 同样， <strong>quark(down)</strong> 被实例化为 <strong>quark&lt;const string&amp;&gt;()</strong> ，进而 <strong>T&amp;&amp;</strong> 经替换与折叠之后变成 <strong>const string&amp;</strong> 。在 C++98/03中，你可能习惯了常量性(constness)隐藏于模板形参中(也就是说可以传 <strong>const Foo</strong> 对象作实参来调用形参为 <strong>T&amp;</strong> 的模板函数，就像 <strong>T&amp;</strong> 会是 <strong>const Foo&amp;</strong> 一样)，在 C++0x 中，左值属性(lvalueness) 也能隐藏于模板形参中。</p>
<p>&nbsp;</p>
<p>那好，这两条特殊规则对我们有什么影响？在 quark() 内部，类型 <strong>T&amp;&amp;</strong> 有着和传给 <strong>quark() </strong>的实参一样的左/右值属性(lvalueness/rvalueness)和常量性。这样 <strong>rvalue 引用就能保持住左右</strong><strong>值</strong><strong>属性和常量性，做到完美</strong><strong>转发</strong><strong>。</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>完美</strong><strong>转发</strong><strong>： std::forward() 和 std::identidy 是怎</strong><strong>样</strong><strong>工作的</strong></p>
<p>&nbsp;</p>
<p>让我们再来看看 outer() :</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T1, typename T2&gt; void outer(T1&amp;&amp; t1, T2&amp;&amp; t2) {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; inner(Forward&lt;T1&gt;(t1), Forward&lt;T2&gt;(t2));</strong></p>
<p><strong>}</strong></p>
<p>&nbsp;</p>
<p>现在我们明白了为什么<strong> outer()</strong> 的形参是 <strong>T1&amp;&amp;</strong> 和 <strong>T2&amp;&amp;</strong> 类型的了，因为它们能够保持住传给 <strong>outer()</strong> 的实参的信息。那为什么这里要调用 <strong>Forward&lt;T1&gt;()</strong> 和 <strong>Forward&lt;T2&gt;()</strong> 呢？还记得么，具名 lvalue 引用和具名 rvalue 引用都是 lvalue 。如果 <strong>outer()</strong> 调用 <strong>inner(t1, t2)</strong> ，那么 <strong>inner()</strong> 总是会当 lvalue 来引用 <strong>t1</strong> 和 <strong>t2</strong> ，这就破坏了完美转发。</p>
<p>&nbsp;</p>
<p>幸 运的是，不具名 lvalue 引用是 lvalue，不具名 rvalue 引用还是 rvalue 。因此，为了将 t1 和 t2 转发给 inner()，我们需要将它们传到一个帮助函数中去，这个帮助函数移除它们的名字，保持住它们的属性信息。这就是 std::forward() 做的事情：</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T&gt; struct Identity {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; typedef T type;</strong></p>
<p><strong>};</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>template &lt;typename T&gt; T&amp;&amp; Forward(typename Identity&lt;T&gt;::type&amp;&amp; t) {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; return t;</strong></p>
<p><strong>}</strong></p>
<p>&nbsp;</p>
<p>当我们调用 <strong>Forward&lt;T1&gt;(t1)</strong> ， <strong>Identidy</strong> 并没有修改 <strong>T1</strong> （很快我们讲到 <strong>Identidy</strong> 对 <strong>T1</strong> 做了什么）。因此 <strong>Forward&lt;T1&gt;()</strong> 接收 <strong>T1&amp;&amp;</strong> ，返回 <strong>T1&amp;&amp;</strong> 。这样就移除了 <strong>t1</strong> 的名字，保持住 <strong>t1</strong> 的类型信息（而不论 <strong>t1</strong> 是什么类型， string&amp; 也好, const string&amp; 也好, string&amp;&amp; 也好或 const string&amp;&amp; 也好）。这样 <strong>inner()</strong> 看到的 <strong>Forward&lt;T1&gt;(t1)</strong> ，与 <strong>outer()</strong> 接收的第一个实参有着相同的信息，包括类型，lvalueness/rvalueness，常量性等等。完美转发就是这样工作的。</p>
<p>&nbsp;</p>
<p>你可能会好奇如果不小心写成 <strong>Forward&lt;T1&amp;&amp;&gt;(t1) </strong>又会怎样呢？（这个错误还是蛮诱人的，因为 <strong>outer() </strong>接收的就是 <strong>T1&amp;&amp; t1</strong> ）。很幸运，没什么坏事情会发生。 <strong>Forward&lt;T1&amp;&amp;&gt;()</strong> 接收与返回的都是 <strong>T1&amp;&amp; &amp;&amp;</strong> ，这会被折叠成 <strong>T1&amp;&amp;</strong> 。于是，<strong>Forward&lt;T1&gt;(t1)</strong> 和 <strong>Forward&lt;T1&amp;&amp;&gt;(t1)</strong> 是等价的，我们更偏好前者，是因为它要短些。</p>
<p>&nbsp;</p>
<p><strong>Identidy</strong> 是做什么用的呢？为什么下面的代码不能工作？</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T&gt; T&amp;&amp; Forward(T&amp;&amp; t) { // BROKEN</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp; return t;</strong></p>
<p><strong>}</strong></p>
<p>&nbsp;</p>
<p>如果 <strong>Forward()</strong> 像是上面那样，它就能被隐式调用（不带明确的模板参数）。当我们传给<strong> Forward()</strong> 一个 lvalue 实参时，模板参数推导就介入了，如我们前面看到的那样会将 <strong>T&amp;&amp;</strong> 变成 <strong>T&amp;</strong>，也就是变成一个 lvalue 引用。问题来了，即使形参 <strong>T1&amp;&amp;</strong> 和 <strong>T2&amp;&amp;</strong> 指明是 rvalue 引用，但在 <strong>outer()</strong> 中，具名的 <strong>t1</strong> 和 <strong>t2</strong> 却是 lvaue ，这个问题是我们一直想要解决的！使用上面那个错误的实现， <strong>Forward&lt;T1&gt;(t1)</strong> 是可以工作的，而 <strong>Foarward(t1)</strong> 虽然能通过编译（很诱人哦）但会出错，就如它就是 <strong>t1</strong> 一样。真是痛苦的源泉啊，因此，<strong>Identity</strong> <strong>被用来阻止模板参数推</strong><strong>导</strong>。<strong>typename Identity&lt;T&gt;::type</strong> 中的那对冒号就像绝缘体，模板参数推导无法穿越它，有模板编程经验的程序员应该对此很熟悉了，因为这在 C++98/03 和 C++0x 中是一样的。（要解释这个是另外的事情了）</p>
<p>&nbsp;</p>
<p><strong>move </strong><strong>语</strong><strong>意：</strong><strong> std::move() </strong><strong>是怎</strong><strong>样</strong><strong>工作的</strong></p>
<p>&nbsp;</p>
<p>现在我们已经学习了模板参数推导和引用折叠的特殊规则，让我们再来看看 std::move() :</p>
<p>&nbsp;</p>
<p><strong>template &lt;typename T&gt; struct RemoveReference {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</strong></p>
<p><strong>};</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>template &lt;typename T&gt; struct RemoveReference&lt;T&amp;&gt; {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</strong></p>
<p><strong>};</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>template &lt;typename T&gt; struct RemoveReference&lt;T&amp;&amp;&gt; {</strong></p>
<p><strong>&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</strong></p>
<p><strong>};</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>template &lt;typename T&gt; typename RemoveReference&lt;T&gt;::type&amp;&amp; Move(T&amp;&amp; t) {</strong></p>
<p><strong>&nbsp;&nbsp; &nbsp;return t;</strong></p>
<p><strong>}</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>RemoveReference </strong>机制基本上是复制 C++0x &lt;type_traits&gt; 中的 <strong>std::remove_reference</strong> 。举例来说，<strong>RemoveReference&lt;string&gt;::type</strong> , <strong>RemoveReference&lt;string&amp;&gt;::type</strong> 和 <strong>RemoveReference&lt;string&amp;&amp;&gt;::type</strong> 都是 <strong>string </strong>。</p>
<p>&nbsp;</p>
<p>同样， <strong>move()</strong> 机制也基本上是复制 C++0x &lt;utility&gt; 中的 <strong>std::move()</strong>。 </p>
<p>&#183; 当调用 <strong>Move(string)</strong>, <strong>string </strong>是一个 lvalue 时， <strong>T</strong> 会被推导为 <strong>string&amp;</strong> ，于是<strong> Move()</strong> 接收的就是 <strong>string&amp;</strong> (经折叠之后)并返回 <strong>string&amp;&amp;</strong> (经 <strong>RemoveReference </strong>之后)。</p>
<p>&nbsp;</p>
<p>&#183; 当调用 <strong>Move(const string)</strong>, <strong>const</strong> <strong>string </strong>是一个 lvalue 时， <strong>T</strong> 会被推导为 <strong>const string&amp;</strong> ，于是 <strong>Move()</strong> 接收的就是 <strong>const string&amp;&amp;</strong> (经折叠之后)并返回 <strong>const string&amp;&amp;</strong> (经 <strong>RemoveReference </strong>之后)。</p>
<p>&nbsp;</p>
<p>&#183; 当调用 <strong>Move(string)</strong>, <strong>string </strong>是一个 rvalue 时， <strong>T</strong> 会被推导为 <strong>string</strong> ，于是<strong> Move()</strong> 接收的就是 <strong>string&amp;&amp;</strong> 并返回 <strong>string&amp;&amp;</strong> 。</p>
<p>&nbsp;</p>
<p>&#183; 当调用 <strong>Move(const string)</strong>, <strong>const</strong> <strong>string </strong>是一个 rvalue 时， <strong>T</strong> 会被推导为 <strong>const string</strong> ，于是 <strong>Move()</strong> 接收的就是 <strong>const string&amp;&amp;</strong> 并返回 <strong>const string&amp;&amp;</strong> 。</p>
<p>&nbsp;</p>
<p>这就是 Move() 如何保持其参数的类型和常量性，还能把 lvalue 转换成 rvalue 的过程。</p>
<p>&nbsp;</p>
<p><strong>回</strong><strong>顾</strong><strong></strong></p>
<p>如果你想对 rvalue 引用有更多了 解，你可以去读有关它们的提案。要注意，提案与现在的决定可能已经不同了， rvalue 引用已经被整合到 C++0x 草案中来了，在那里它得到持续的改进。有些提案或已不再正确，或已过时，或已有了替代方案，就没有被采纳。无论怎样，它们还是能提供一些有用信息的。</p>
<p>&nbsp;</p>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">N1377</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">N1385</a>, 和 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1690.html">N1690</a> 是主要的提案，<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html">N2118</a> 包含被整合进标准草案之前的最后版本。 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1784.htm">N1784</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm">N1821</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2377.htm">N2377</a>, 和 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm">N2439</a> 记录了&#8220;将 Move 语意扩展到 *this &#8221;的演化过程，这个也被整合到 C++0x 中来了，但还没有在VC10 中得到实现。</p>
<p>&nbsp;</p>
<p><strong>展望</strong></p>
<p><a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2812.html">N2812</a> &#8220;Rvalue 引用的安全问题（以及如何解决）&#8221; 提出了对初始化规则的修改，它禁止 rvalue 引用绑定到 lvalue 。 这不会影响 move 语意和完美转发，所以它不会让你刚学到的新技术失效（它只是修改了 std::move() 和 std::forward() 的实现）。</p>
<p>&nbsp;</p>
<p>Stephan T. Lavavej</p>
<p>Visual C++ Libraries Developer</p>
<p>Published Tuesday, February 03, 2009 9:27 AM by <a href="http://blogs.msdn.com/user/Profile.aspx?UserID=33825">vcblog</a></p>
<p>翻译：<a href="http://www.cppblog.com/kesalin/">飘飘白云</a></p>
<p>&nbsp;</p>
<p style="TEXT-ALIGN: center">(转载时请注明作者和出处。未经许可，请勿用于商业用途)</p>
<p style="TEXT-ALIGN: center">&nbsp;&lt; <a href="http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html">第一页</a>， <a href="http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html">第二页</a>， 本页&gt;</p>
<br>
<p>&nbsp;</p>
<br><br>
<img src ="http://www.cppblog.com/kesalin/aggbug/86851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-06-05 15:09 <a href="http://www.cppblog.com/kesalin/archive/2009/06/05/86851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【译】VC10中的C++0x特性 part 2（2）:右值引用</title><link>http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Thu, 04 Jun 2009 01:37:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/86720.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/86720.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/86720.html</trackback:ping><description><![CDATA[<p style="TEXT-ALIGN: center">
<h3 style="FONT-FAMILY: 宋体; TEXT-ALIGN: center">【译】VC10中的C++0x特性 part 2（2）:右值引用</h3>
来源：<a title=vcvlog href="http://blogs.msdn.com/vcblog/archive/2008/10/28/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx" target=_blank>vcblog</a> 作者：Stephan T. Lavavej 翻译：<a title=飘飘白云的C++博客 href="http://www.cppblog.com/kesalin" target=_blank>飘飘白云</a> &nbsp;
<p>&#160;</p>
<p style="FONT-SIZE: 12pt"></p>
<p style="TEXT-ALIGN: center">(转载时请注明作者和出处。未经许可，请勿用于商业用途) <br></p>
<p>简介 </p>
<div class=postText><style>
<!--
/* Font Definitions */
@font-face
{font-family:Wingdings;
panose-1:5 0 0 0 0 0 0 0 0 0;
mso-font-charset:2;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:0 268435456 0 0 -2147483648 0;}
@font-face
{font-family:"MS Mincho";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-alt:"ＭＳ 明朝";
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:Century;
panose-1:2 4 6 4 5 5 5 2 3 4;
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:647 0 0 0 159 0;}
@font-face
{font-family:"MS PGothic";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:Verdana;
panose-1:2 11 6 4 3 5 4 4 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:536871559 0 0 0 415 0;}
@font-face
{font-family:"\@MS PGothic";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:"\@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@MS Mincho";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"MS Mincho";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;
mso-fareast-language:JA;}
h1
{mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
mso-pagination:widow-orphan;
mso-outline-level:1;
font-size:24.0pt;
font-family:"MS PGothic";
mso-bidi-font-family:"MS PGothic";
mso-fareast-language:JA;}
p.MsoHeader, li.MsoHeader, div.MsoHeader
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
tab-stops:center 212.6pt right 425.2pt;
layout-grid-mode:char;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"MS Mincho";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;
mso-fareast-language:JA;}
p.MsoFooter, li.MsoFooter, div.MsoFooter
{margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
tab-stops:center 212.6pt right 425.2pt;
layout-grid-mode:char;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"MS Mincho";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;
mso-fareast-language:JA;}
a:link, span.MsoHyperlink
{color:blue;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{color:purple;
text-decoration:underline;
text-underline:single;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:595.3pt 841.9pt;
margin:99.25pt 3.0cm 3.0cm 3.0cm;
mso-header-margin:42.55pt;
mso-footer-margin:49.6pt;
mso-paper-source:0;
layout-grid:18.0pt;}
div.Section1
{page:Section1;}
-->
</style>
<p>这一系列文章介绍Microsoft Visual Studio 2010 中支持的C++ 0x特性，目前有三部分。 <br><a title="VC10中的C++0x特性 part 1" href="http://blog.csdn.net/kesalin/archive/2009/05/28/4222214.aspx" target=_blank>Part 1</a> ：介绍了Lambdas， 赋予新意义的auto，以及 static_assert； <br>Part 2( <a title="VC10中的C++0x特性 part 2 第一部分" href="http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html" target=_blank>一</a> , <a title="VC10中的C++0x特性 part 2 第二部分" href="http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html" target=_blank>二</a> , <a title="VC10中的C++0x特性 part 2 第三部分 " href="http://www.cppblog.com/kesalin/archive/2009/06/05/86851.html" target=_blank>三</a> )：介绍了右值引用（Rvalue References）； <br><a title="VC10中的C++0x特性 part 3" href="http://www.cppblog.com/kesalin/archive/2009/06/07/86960.html" target=_blank>Part 3</a>：介绍了表达式类型（decltype）<br><br>VC10中的C++0x特性 Part 1,2,3 译文打包下载（doc 和 pdf 格式）： <a title="VC10中的C++0x特性（Part 1,2,3）译文doc和pdf文档" href="http://www.cppblog.com/Files/kesalin/Cplusplus0x_in_VC10.zip" target=_blank>点此下载</a></p>
</div>
<br>
<object id=ieooui classid=clsid:38481807-ca0e-42d2-bf39-b33af135cc4d></object><style>
st1\:*{behavior:url(#ieooui) }
</style>本文为 Part 2 第二页。
<p style="FONT-FAMILY: 宋体"></p>
<br style="FONT-FAMILY: 宋体">
<meta content=Word.Document name=ProgId>
<meta content="Microsoft Word 11" name=Generator>
<meta content="Microsoft Word 11" name=Originator>
<link style="FONT-FAMILY: 宋体" href="file:///C:%5CDOCUME%7E1%5CLUO%7E1.ZHA%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C02%5Cclip_filelist.xml" rel=File-List><style>
<!--
/* Font Definitions */
@font-face
{font-family:"ＭＳ 明朝";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-alt:"MS Mincho";
mso-font-charset:128;
mso-generic-font-family:roman;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:SimSun;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:宋体;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:Century;
panose-1:2 4 6 4 5 5 5 2 3 4;
mso-font-charset:0;
mso-generic-font-family:roman;
mso-font-pitch:variable;
mso-font-signature:647 0 0 0 159 0;}
@font-face
{font-family:"ＭＳ Ｐゴシック";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:"\@SimSun";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"\@ＭＳ Ｐゴシック";
panose-1:2 11 6 0 7 2 5 8 2 4;
mso-font-charset:128;
mso-generic-font-family:modern;
mso-font-pitch:variable;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
@font-face
{font-family:"\@ＭＳ 明朝";
panose-1:2 2 6 9 4 2 5 8 3 4;
mso-font-charset:128;
mso-generic-font-family:roman;
mso-font-pitch:fixed;
mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0mm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:Century;
mso-fareast-font-family:"ＭＳ 明朝";
mso-bidi-font-family:"Times New Roman";
mso-font-kerning:1.0pt;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:612.0pt 792.0pt;
margin:99.25pt 30.0mm 30.0mm 30.0mm;
mso-header-margin:36.0pt;
mso-footer-margin:36.0pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
</style>
<p style="FONT-FAMILY: 宋体"><strong>move </strong><strong>语意：从</strong><strong> lvalue </strong><strong>移动</strong></p>
<p style="FONT-FAMILY: 宋体"><br></p>
<p style="FONT-FAMILY: 宋体">现在，如果你喜欢用拷贝赋值函数来实现你的拷贝构造函数该怎样做呢，那你也可能试图用 move 拷贝赋值函数来实现 move 构造函数。这样作是可以的，但是你得小心。下面就是一个错误的实现：</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;type unified_wrong.cpp</p>
<p style="FONT-FAMILY: courier new">#include &lt;stddef.h&gt;</p>
<p style="FONT-FAMILY: courier new">#include &lt;iostream&gt;</p>
<p style="FONT-FAMILY: courier new">#include &lt;ostream&gt;</p>
<p style="FONT-FAMILY: courier new">using namespace std;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">class remote_integer {</p>
<p style="FONT-FAMILY: courier new">public:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Default constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; explicit remote_integer(const int n) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Unary constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(n);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer(const remote_integer&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Copy constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *this = other;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">#ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer(remote_integer&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "MOVE CONSTRUCTOR." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *this = other; // WRONG</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">#endif // #ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer&amp; operator=(const remote_integer&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Copy assignment operator." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this != &amp;other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (other.m_p) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(*other.m_p);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">#ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer&amp; operator=(remote_integer&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "MOVE ASSIGNMENT OPERATOR." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this != &amp;other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = other.m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; other.m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">#endif // #ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; ~remote_integer() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Destructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int get() const {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return m_p ? *m_p : 0;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">private:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int * m_p;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">remote_integer frumple(const int n) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; if (n == 1729) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return remote_integer(1729);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer ret(n * n);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; return ret;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">int main() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer x = frumple(5);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; cout &lt;&lt; x.get() &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer y = frumple(1729);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; cout &lt;&lt; y.get() &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;cl /EHsc /nologo /W4 /O2 unified_wrong.cpp</p>
<p style="FONT-FAMILY: courier new">unified_wrong.cpp</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;unified_wrong</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">Copy constructor.</p>
<p style="FONT-FAMILY: courier new">Copy assignment operator.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">25</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">1729</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;cl /EHsc /nologo /W4 /O2 /DMOVABLE unified_wrong.cpp</p>
<p style="FONT-FAMILY: courier new">unified_wrong.cpp</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;unified_wrong</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">MOVE CONSTRUCTOR.</p>
<p style="FONT-FAMILY: courier new">Copy assignment operator.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">25</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">1729</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">(编译器在这里进行了返回值优化(RVO)，但不是具名返回值优化(NRVO)。就像我之前提到的，有些拷贝构造函数被 RVO 或 NRVO 优化掉了，但编译器并不总是能够做这样的优化，这时剩余的就由 move 构造函数来优化。)</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">move 构造函数中标记为 WRONG 的那一行，调用了拷贝赋值函数，编译能通过也能运行，但这违背了 move 构造函数的本意。（译注：因为那个拷贝赋值函数只是进行普通的拷贝赋值，而不是 move 赋值！）</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">这是怎么回事呢？记住：在C++98/03中，具名 lvalue 引用是左值(给定语句 int&amp; r = *p; r 是 lvalue)，不具名 lvalue 引用还是左值(给定语句 vector&lt;int&gt; v(10, 1729)， v[0] 返回 int&amp;， 你可以对这个不具名 lvalue 引用取址)。但是 rvalue 引用就不一样了：</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体"><strong></strong><strong> </strong><strong>具名</strong><strong> </strong><strong>lvalue</strong><strong> </strong><strong>引用是</strong><strong> </strong><strong>lvalue</strong><strong>。</strong><strong></strong></p>
<p style="FONT-FAMILY: 宋体"><strong></strong><strong> </strong><strong>不具名</strong><strong> rvalue</strong><strong> </strong><strong>引用是</strong><strong> </strong><strong>rvalue</strong><strong>。</strong><strong></strong></p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">一个具名 rvalue 引用是一个 lvalue 是因为可以对它施加多重操作，重复使用。相反，如果它是一个 ravlue 的话，那么对它施加的第一个操作能够&#8220;窃取&#8221;它，而后续操作就没机会了。这里的&#8220;窃取&#8221;是说不会被察觉到，所以这是行不通的。另一方面，不具名 rvalue 引用不能被重复使用，所以它仍保持右值(rvalueness)语意。</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">如果你真的打算用 move 赋值函数来实现 move 构造函数，你需要从 lvalue move，就像是从 rvalue move 一样。C++0x &lt;utility&gt; 中的 std::move() 具备这样的能力，VC10将会有这个（实际上，开发版中已经有了），但VC10 TCP版还没有，所以我会教你从头做起：</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;type unified_right.cpp</p>
<p style="FONT-FAMILY: courier new">#include &lt;stddef.h&gt;</p>
<p style="FONT-FAMILY: courier new">#include &lt;iostream&gt;</p>
<p style="FONT-FAMILY: courier new">#include &lt;ostream&gt;</p>
<p style="FONT-FAMILY: courier new">using namespace std;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; struct RemoveReference {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; struct RemoveReference&lt;T&amp;&gt; {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; struct RemoveReference&lt;T&amp;&amp;&gt; {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; typename RemoveReference&lt;T&gt;::type&amp;&amp; Move(T&amp;&amp; t) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; return t;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">class remote_integer {</p>
<p style="FONT-FAMILY: courier new">public:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Default constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; explicit remote_integer(const int n) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Unary constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(n);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer(const remote_integer&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Copy constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *this = other;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">#ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer(remote_integer&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "MOVE CONSTRUCTOR." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *this = Move(other); // RIGHT</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">#endif // #ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer&amp; operator=(const remote_integer&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Copy assignment operator." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this != &amp;other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (other.m_p) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(*other.m_p);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">#ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer&amp; operator=(remote_integer&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "MOVE ASSIGNMENT OPERATOR." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this != &amp;other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = other.m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; other.m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">#endif // #ifdef MOVABLE</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; ~remote_integer() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Destructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int get() const {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return m_p ? *m_p : 0;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">private:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int * m_p;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">remote_integer frumple(const int n) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; if (n == 1729) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return remote_integer(1729);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer ret(n * n);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; return ret;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">int main() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer x = frumple(5);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; cout &lt;&lt; x.get() &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer y = frumple(1729);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; cout &lt;&lt; y.get() &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;cl /EHsc /nologo /W4 /O2 /DMOVABLE unified_right.cpp</p>
<p style="FONT-FAMILY: courier new">unified_right.cpp</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;unified_right</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">MOVE CONSTRUCTOR.</p>
<p style="FONT-FAMILY: courier new">MOVE ASSIGNMENT OPERATOR.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">25</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">1729</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">（我将交替使用 std::move() 和我自己的 Move()，因为它们的实现是等价的） std::move() 是怎样工作的呢？目前，我只能跟你说这是&#8220;魔法&#8221;。（后面会有完整的解释，并不复杂，但它与模板参数推导和引用折叠（reference collapsing，译注：引用的引用）有 关，后面讲完美转发的时候我们还会遇到这两个东西）。我可以用一个具体的例子来略过&#8220;魔法&#8221;：给定一个 string 类型的左值，像前面重载决议例子中的 up ，std::move(up) 调用 string&amp;&amp; std::move(string&amp;)，这个函数返回一个不具名的 rvalue 引用，它是一个 rvalue。给定一个 string 类型的 rvalue，像前面重载决议例子中的 strange()， std::move(strange()) 调用 string&amp;&amp; std::move(string&amp;&amp;)，同样这个函数还是返回一个不具名的 rvalue，还是 rvalue。</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">std::move() 除了让你能用 move 复制函数来实现 move 构造函数之外，还能在其他地方发挥作用。无论何时，只要你有一个左值，而它的值也不再重要了（例如，它将被销毁或被赋值），你就可以使用 std::move(你的左值表达式) 来使用 move 语意。</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体"><strong>move </strong><strong>语意：可移动成员（</strong><strong>movable member)</strong></p>
<p style="FONT-FAMILY: 宋体"><br></p>
<p style="FONT-FAMILY: 宋体">C++0x 的标准类型（像 vector, string, regex） 都有 move 构造函数和 move 赋值函数。而且我们也已经看到了如何在我们自己的类中通过手动管理资源来实现 move 语意（像前面的 remote_integer 类）。如果类中包含可移动数据成员（像 vector, string, regex, remote_integer ）时该怎么办呢？编译器不会自动帮我们自动产生 move 构造函数和 move 赋值函数，所以我们必须手动编写它们。很幸运，有了 std::move() 编写它们是很容易的。</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;type point.cpp</p>
<p style="FONT-FAMILY: courier new">#include &lt;stddef.h&gt;</p>
<p style="FONT-FAMILY: courier new">#include &lt;iostream&gt;</p>
<p style="FONT-FAMILY: courier new">#include &lt;ostream&gt;</p>
<p style="FONT-FAMILY: courier new">using namespace std;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; struct RemoveReference {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; struct RemoveReference&lt;T&amp;&gt; {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; struct RemoveReference&lt;T&amp;&amp;&gt; {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; typedef T type;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">template &lt;typename T&gt; typename RemoveReference&lt;T&gt;::type&amp;&amp; Move(T&amp;&amp; t) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; return t;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">class remote_integer {</p>
<p style="FONT-FAMILY: courier new">public:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Default constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; explicit remote_integer(const int n) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Unary constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(n);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer(const remote_integer&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Copy constructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (other.m_p) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(*other.m_p);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer(remote_integer&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "MOVE CONSTRUCTOR." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = other.m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; other.m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer&amp; operator=(const remote_integer&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "Copy assignment operator." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this != &amp;other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (other.m_p) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = new int(*other.m_p);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer&amp; operator=(remote_integer&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout &lt;&lt; "MOVE ASSIGNMENT OPERATOR." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this != &amp;other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_p = other.m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; other.m_p = NULL;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; ~remote_integer() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;cout &lt;&lt; "Destructor." &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_p;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int get() const {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return m_p ? *m_p : 0;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">private:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int * m_p;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">class remote_point {</p>
<p style="FONT-FAMILY: courier new">public:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_point(const int x_arg, const int y_arg)</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : m_x(x_arg), m_y(y_arg) { }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_point(remote_point&amp;&amp; other)</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : m_x(Move(other.m_x)),</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_y(Move(other.m_y)) { }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_point&amp; operator=(remote_point&amp;&amp; other) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_x = Move(other.m_x);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_y = Move(other.m_y);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return *this;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int x() const { return m_x.get(); }</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; int y() const { return m_y.get(); }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">private:</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer m_x;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_integer m_y;</p>
<p style="FONT-FAMILY: courier new">};</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">remote_point five_by_five() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; return remote_point(5, 5);</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">remote_point taxicab(const int n) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; if (n == 0) {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return remote_point(1, 1728);</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_point ret(729, 1000);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; return ret;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">int main() {</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; remote_point p = taxicab(43112609);</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; cout &lt;&lt; "(" &lt;&lt; p.x() &lt;&lt; ", " &lt;&lt; p.y() &lt;&lt; ")" &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; p = five_by_five();</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">&nbsp;&nbsp;&nbsp; cout &lt;&lt; "(" &lt;&lt; p.x() &lt;&lt; ", " &lt;&lt; p.y() &lt;&lt; ")" &lt;&lt; endl;</p>
<p style="FONT-FAMILY: courier new">}</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;cl /EHsc /nologo /W4 /O2 point.cpp</p>
<p style="FONT-FAMILY: courier new">point.cpp</p>
<p style="FONT-FAMILY: courier new">&nbsp;</p>
<p style="FONT-FAMILY: courier new">C:\Temp&gt;point</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">MOVE CONSTRUCTOR.</p>
<p style="FONT-FAMILY: courier new">MOVE CONSTRUCTOR.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">(729, 1000)</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">Unary constructor.</p>
<p style="FONT-FAMILY: courier new">MOVE ASSIGNMENT OPERATOR.</p>
<p style="FONT-FAMILY: courier new">MOVE ASSIGNMENT OPERATOR.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">(5, 5)</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: courier new">Destructor.</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">现在你看到啦，按成员移动（memberwise move）是很容易做到的。注意， remote_point 的 move 赋值函数没有进行自我赋值检查，是因为 remote_integer 已经检查过了。也要注意到 remote_point 隐式声明的拷贝构造函数，拷贝赋值函数和析构函数都正常运作。</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">到现在，你应该对 move 语意已经非常熟悉了。（希望不是抓狂啊！）为了测试你新获得的这个不可思议的技能，请为前面的例子写一个 +() 操作符函数当作练习吧。</p>
<p style="FONT-FAMILY: 宋体">&nbsp;</p>
<p style="FONT-FAMILY: 宋体">最后的提醒：只要你的类支持 move 语意，你就应该实现 move 构造函数和 move 赋值函数。因为不仅仅是你平常使用这些类时可从 move 语意中获利， STL 容器和算法也能从中获利，通过廉价的 move 省下昂贵的拷贝开销。</p>
<p style="FONT-FAMILY: 宋体"><br></p>
<p style="FONT-FAMILY: 宋体; TEXT-ALIGN: center">(转载请注明出处，作者与译者信息，请勿用于商业用途)&nbsp;</p>
<p style="FONT-FAMILY: 宋体"><br></p>
<p style="FONT-FAMILY: 宋体; TEXT-ALIGN: center">&nbsp;&lt; <a href="http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html">前一页</a>&nbsp; 后一页 &gt;<br></p>
<br style="FONT-FAMILY: 宋体">
<img src ="http://www.cppblog.com/kesalin/aggbug/86720.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-06-04 09:37 <a href="http://www.cppblog.com/kesalin/archive/2009/06/04/86720.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【译】VC10中的C++0x特性 part 2（1）:右值引用</title><link>http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Mon, 01 Jun 2009 12:40:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/86461.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/86461.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/86461.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这一系列文章介绍Microsoft Visual Studio 2010 中支持的C++ 0x特性，目前有三部分。<br>Part 1：介绍了Lambdas， 赋予新意义的auto，以及 static_assert；<br>Part 2：介绍了右值引用（Rvalue References）；<br>Part 3：介绍了表达式类型（decltype）。<br><br>本文为Part 2 的第一页。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/86461.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-06-01 20:40 <a href="http://www.cppblog.com/kesalin/archive/2009/06/01/86461.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【译】VC10中的C++0x特性 part 1：Lambdas，auto，以及 static_assert</title><link>http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Thu, 28 May 2009 03:27:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/85983.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html#Feedback</comments><slash:comments>14</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/85983.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/85983.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Microsoft Visual Studio 2010所带的Visual C++编译器对四个C++0x语言特性提供了支持，也就是 lambdas，auto，static_assert，以及 rvalue references 。今天，我将详细介绍前三个特性。（很快我将贡献一整篇幅的文章来解释右值引用，仅仅是因为再在这里解释的话将会加大这篇已经很长的文章的篇幅）&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/85983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-05-28 11:27 <a href="http://www.cppblog.com/kesalin/archive/2009/05/28/85983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>3D游戏Demo-添加天空盒，云层，海水，植被</title><link>http://www.cppblog.com/kesalin/archive/2009/04/25/81042.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Sat, 25 Apr 2009 08:07:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2009/04/25/81042.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/81042.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2009/04/25/81042.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/81042.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/81042.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这两天为游戏添加了如下元素：<br><br>光照效果：根据时间变化光照效果。另外加了太阳光，这个效果还不太对头（调试中）<br>天空盒，云层效果：根据时间变化效果，显现出黎明，白天，傍晚和夜晚四个不同场景<br>海水：简单的波动效果<br>植被：草木<br><br>贴张效果图：&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2009/04/25/81042.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/81042.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2009-04-25 16:07 <a href="http://www.cppblog.com/kesalin/archive/2009/04/25/81042.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>