﻿<?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++博客-罗朝辉（飘飘白云）-随笔分类-C/C++</title><link>http://www.cppblog.com/kesalin/category/3832.html</link><description>关注嵌入式操作系统，移动平台，图形开发。&lt;a href="http://weibo.com/kesalin/" target="_top"&gt;--&gt;加微博 ^_^&lt;/a&gt;</description><language>zh-cn</language><lastBuildDate>Thu, 10 Jul 2014 19:03:32 GMT</lastBuildDate><pubDate>Thu, 10 Jul 2014 19:03:32 GMT</pubDate><ttl>60</ttl><item><title>如何在遍历中使用 iterator/reverse_iterator 删除元素</title><link>http://www.cppblog.com/kesalin/archive/2014/07/10/cpp_stl.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Thu, 10 Jul 2014 01:42:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2014/07/10/cpp_stl.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/206672.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2014/07/10/cpp_stl.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/206672.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/206672.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 众所周知，在使用迭代器遍历 STL 容器时，需要特别留意是否在循环中修改了迭代器而导致迭代器失效的情形。下面我来总结一下在对各种容器进行正向和反向遍历过程中删除元素时，正确更新迭代器的用法。本文完整源码：点此查看<br>首先，要明白使用正向迭代器（iterator）进行反向遍历是错误的用法，要不干嘛要有反向迭代器呢（reverse_iterator）。其次，根据容器的特性，遍历删除操作的用法可以分为两组，第一组是 list 和 vector，第二组是 map 和 set。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2014/07/10/cpp_stl.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/206672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2014-07-10 09:42 <a href="http://www.cppblog.com/kesalin/archive/2014/07/10/cpp_stl.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让gcc支持成员函数模板的trick</title><link>http://www.cppblog.com/kesalin/archive/2013/07/12/gcc_member_function_template.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Fri, 12 Jul 2013 14:04:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2013/07/12/gcc_member_function_template.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/201753.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2013/07/12/gcc_member_function_template.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/201753.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/201753.html</trackback:ping><description><![CDATA[<p data-mce-="" style="text-align: center; margin-top: 14px; margin-bottom: 14px; font-family: verdana, Arial, Helvetica, sans-serif;">让gcc支持成员函数模板的trick</p><p data-mce-="" style="text-align: center; margin-top: 14px; margin-bottom: 14px; font-family: verdana, Arial, Helvetica, sans-serif;">罗朝辉 (<a href="http://www.cppblog.com/kesalin/" target="_blank" data-mce-href="http://www.cnblogs.com/kesalin/">http://www.cppblog.com/kesalin/</a>)</p><div align="center" style="font-family: verdana, Arial, Helvetica, sans-serif;">本文遵循&#8220;<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/cn/" target="_blank" data-mce-href="http://creativecommons.org/licenses/by-nc-sa/2.5/cn/">署名-非商业用途-保持一致</a>&#8221;创作公用协议</div><div align="center" data-mce-="" style="font-family: verdana, Arial, Helvetica, sans-serif;">&nbsp;</div><div align="center" data-mce-="" style="text-align: left; font-family: verdana, Arial, Helvetica, sans-serif;">gcc 4.7.3 不支持成员函数模板特化。如下代码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />#ifndef&nbsp;__MEMFUNTEMPLATE_H__<br /><span style="color: #0000FF; ">#define</span>&nbsp;__MEMFUNTEMPLATE_H__<br /><br />#include&nbsp;&lt;stdio.h&gt;<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;Base&nbsp;{};<br /><span style="color: #0000FF; ">class</span>&nbsp;Derived&nbsp;:&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;Base&nbsp;{};<br /><br /><span style="color: #0000FF; ">struct</span>&nbsp;Functor&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;template&nbsp;&lt;typename&nbsp;T&gt;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;function()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("&nbsp;Primary&nbsp;template<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;template&lt;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;function&lt;<span style="color: #0000FF; ">int</span>&gt;(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("&nbsp;Specialization&nbsp;for&nbsp;int<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;template&lt;&gt;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;function&lt;Base&nbsp;*&gt;()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("&nbsp;Specialization&nbsp;for&nbsp;Base&nbsp;*<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.\n");<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;Tester&nbsp;{<br /><span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;DoTest()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Functor&nbsp;functor;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functor.function&lt;<span style="color: #0000FF; ">char</span>&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functor.function&lt;<span style="color: #0000FF; ">int</span>&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functor.function&lt;Base&nbsp;*&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;functor.function&lt;Derived&nbsp;*&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br /><span style="color: #0000FF; ">#endif</span>&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;__MEMFUNTEMPLATE_H__</span></div></div><div align="center" data-mce-=""><p style="font-family: verdana, Arial, Helvetica, sans-serif; text-align: left; margin-top: 14px; margin-bottom: 14px;">在 VS2010 中编译运行是没有问题的，但在 gcc 4.7.3下，编译都通不过：<br /></p><div style="font-family: verdana, Arial, Helvetica, sans-serif; background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><div style="text-align: left;">../src/MemFunTemplate.h:21:14:&nbsp;error:&nbsp;&lt;strong&gt;<span style="color: #0000ff;">explicit</span>&nbsp;specialization&nbsp;<span style="color: #0000ff;">in</span>&nbsp;non-<span style="color: #0000ff;">namespace</span>&nbsp;scope&lt;/strong&gt;&nbsp;&#8216;<span style="color: #0000ff;">struct</span>&nbsp;Functor&#8217;</div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><div style="text-align: left;">../src/MemFunTemplate.h:22:24:&nbsp;error:&nbsp;template-id&nbsp;&#8216;function&lt;<span style="color: #0000ff;">int</span>&gt;&#8217;&nbsp;<span style="color: #0000ff;">in</span>&nbsp;declaration&nbsp;of&nbsp;primary&nbsp;template</div><div style="text-align: left;">../src/MemFunTemplate.h:26:14:&nbsp;error:&nbsp;<span style="color: #0000ff;">explicit</span>&nbsp;specialization&nbsp;<span style="color: #0000ff;">in</span>&nbsp;non-<span style="color: #0000ff;">namespace</span>&nbsp;scope&nbsp;&#8216;<span style="color: #0000ff;">struct</span>&nbsp;Functor&#8217;</div><div style="text-align: left;">../src/MemFunTemplate.h:26:38:&nbsp;error:&nbsp;template-id&nbsp;&#8216;function&lt;Base*&gt;&#8217;&nbsp;<span style="color: #0000ff;">in</span>&nbsp;declaration&nbsp;of&nbsp;primary&nbsp;template</div><div style="text-align: left;">../src/MemFunTemplate.h:26:21:&nbsp;error:&nbsp;&#8216;<span style="color: #0000ff;">void</span>&nbsp;Functor::function()&#8217;&nbsp;cannot&nbsp;be&nbsp;overloaded</div><div style="text-align: left;">../src/MemFunTemplate.h:22:10:&nbsp;error:&nbsp;with&nbsp;&#8216;<span style="color: #0000ff;">void</span>&nbsp;Functor::function()&#8217;</div><div style="text-align: left;">../src/MemFunTemplate.cpp:&nbsp;In&nbsp;function&nbsp;&#8216;<span style="color: #0000ff;">int</span>&nbsp;main()&#8217;:</div><div style="text-align: left;">../src/MemFunTemplate.cpp:17:2:&nbsp;error:&nbsp;&#8216;DoTest&#8217;&nbsp;<span style="color: #0000ff;">is</span>&nbsp;not&nbsp;a&nbsp;member&nbsp;of&nbsp;&#8216;Functor&#8217;</div></div><p style="font-family: verdana, Arial, Helvetica, sans-serif; text-align: left; margin-top: 14px; margin-bottom: 14px;"><br />为了达到近似成员函数模板特化的效果，可以利用成员函数主模板以及重载函数来实现：<br /></p><div style="background-color: #eeeeee; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br /><div style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; text-align: left;"><span style="color: #008000;">/*</span></div><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #008000;"><div style="text-align: left;">&nbsp;*&nbsp;MemFunTemplate.h</div><div style="text-align: left;">&nbsp;*</div><div style="text-align: left;">&nbsp;*&nbsp;&nbsp;Created&nbsp;on:&nbsp;Jul&nbsp;12,&nbsp;2013</div><div style="text-align: left;">&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Author:&nbsp;<span style="text-decoration: underline;">http://blog.csdn.net/kesalin/</span></div></span><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #008000;"><div style="text-align: left;">&nbsp;*/</div></span><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2"><br /></font></div><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">#ifndef&nbsp;MEMFUNTEMPLATE_H_</div></font><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">#define<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;MEMFUNTEMPLATE_H_</font></div></span><div style="text-align: left;"></div><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">#include&nbsp;&lt;stdio.h&gt;</div></font><div style="text-align: left;"></div><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">template&lt;typename&nbsp;T&gt;</div></font><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">struct<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;DummyIdentity&nbsp;{</font></div></span><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; typedef&nbsp;T&nbsp;type;</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">};</div></font><div style="text-align: left;"></div><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">class<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;Base&nbsp;{};</font></div></span><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">class<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;Derived&nbsp;:&nbsp;</font>public<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;Base&nbsp;{};</font></div></span><div style="text-align: left;"></div><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">struct<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;Functor&nbsp;{</font></div></span><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp; template&nbsp;&lt;typename&nbsp;T&gt;&nbsp;</font><span style="font-size: 13px; color: #0000ff;">void</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;function()&nbsp;{</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; function(DummyIdentity&lt;T&gt;());</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; }</div></font><div style="text-align: left;"></div><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">private<font face="verdana, Arial, Helvetica, sans-serif" size="2">:</font></div></span><div style="text-align: left;"></div><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; template&nbsp;&lt;typename&nbsp;T&gt;</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp;&nbsp;</font><span style="font-size: 13px; color: #0000ff;">void</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;function(DummyIdentity&lt;T&gt;)&nbsp;{</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; printf("&nbsp;Primary&nbsp;template&nbsp;DummyIdentity&lt;T&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.\n");</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; }</div></font><div style="text-align: left;"></div><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp;&nbsp;</font><span style="font-size: 13px; color: #0000ff;">void</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;function(DummyIdentity&lt;</font><span style="font-size: 13px; color: #0000ff;">int</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&gt;)&nbsp;{</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; printf("&nbsp;overload&nbsp;function&nbsp;for&nbsp;DummyIdentity&lt;int&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.\n");</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; }</div></font><div style="text-align: left;"></div><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp;&nbsp;</font><span style="font-size: 13px; color: #0000ff;">void</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;function(DummyIdentity&lt;Base&nbsp;*&gt;)&nbsp;{</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; printf("&nbsp;overload&nbsp;function&nbsp;for&nbsp;DummyIdentity&lt;Base&nbsp;*&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.\n");</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; }</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">};</div></font><div style="text-align: left;"></div><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">class<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;Tester&nbsp;{</font></div></span><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">public<font face="verdana, Arial, Helvetica, sans-serif" size="2">:</font></div></span><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp;&nbsp;</font><span style="font-size: 13px; color: #0000ff;">static</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;</font><span style="font-size: 13px; color: #0000ff;">void</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;DoTest()</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; {</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; Functor&nbsp;functor;</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp; &nbsp; &nbsp; functor.function&lt;</font><span style="font-size: 13px; color: #0000ff;">char</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&gt;();</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;"><font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp; &nbsp; &nbsp; &nbsp; functor.function&lt;</font><span style="font-size: 13px; color: #0000ff;">int</span><font face="verdana, Arial, Helvetica, sans-serif" size="2">&gt;();</font></div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; functor.function&lt;Base&nbsp;*&gt;();</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; &nbsp; &nbsp; functor.function&lt;Derived&nbsp;*&gt;();</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">&nbsp; &nbsp; }</div></font><font face="verdana, Arial, Helvetica, sans-serif" size="2"><div style="text-align: left;">};</div></font><div style="text-align: left;"></div><span style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 13px; color: #0000ff;"><div style="text-align: left;">#endif<font face="verdana, Arial, Helvetica, sans-serif" size="2">&nbsp;/*&nbsp;MEMFUNTEMPLATE_H_&nbsp;*/</font></div></span></div><p style="font-family: verdana, Arial, Helvetica, sans-serif; text-align: left; margin-top: 14px; margin-bottom: 14px;"><br />调用 DoTest() 运行结果如下：</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><div style="text-align: left;">&nbsp;Primary&nbsp;template&nbsp;DummyIdentity&lt;T&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.</div><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><div style="text-align: left;">&nbsp;overload&nbsp;function&nbsp;<span style="color: #0000ff;">for</span>&nbsp;DummyIdentity&lt;<span style="color: #0000ff;">int</span>&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.</div><div style="text-align: left;">&nbsp;overload&nbsp;function&nbsp;<span style="color: #0000ff;">for</span>&nbsp;DummyIdentity&lt;Base&nbsp;*&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.</div><div style="text-align: left;">&nbsp;Primary&nbsp;template&nbsp;DummyIdentity&lt;T&gt;<img src="http://www.cppblog.com/Images/dot.gif"  alt="" />.</div></div><p style="font-family: verdana, Arial, Helvetica, sans-serif; text-align: left; margin-top: 14px; margin-bottom: 14px;"><span data-mce-style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.5;" style="line-height: 1.5;"><br />注意：</span></p><p style="font-family: verdana, Arial, Helvetica, sans-serif; text-align: left; margin-top: 14px; margin-bottom: 14px;"><span data-mce-style="font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 1.5;" style="line-height: 1.5;">VS2010 版本的代码，模板形参为 T，在实例化不会进行隐式类型转换。即用&nbsp;</span>Derived * 当作实参调用的是主模板，而不是 Base * 特化版本</p><p style="font-family: verdana, Arial, Helvetica, sans-serif; text-align: left; margin-top: 14px; margin-bottom: 14px;">而在 gcc &nbsp;下，模板形参虽然也为T，但影响重载决议的 function 参数为：DummyIdentity&lt;T&gt;，用不同的实际参数实例化该模板，得到的是一堆重载函数。因此用&nbsp;Derived * 当作实参时，调用的函数自然就是实例化的&nbsp;void function(DummyIdentity&lt;T&gt;)了。</p></div><div align="center" data-mce-="" style="text-align: left; font-family: verdana, Arial, Helvetica, sans-serif;">&nbsp;</div><img src ="http://www.cppblog.com/kesalin/aggbug/201753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2013-07-12 22:04 <a href="http://www.cppblog.com/kesalin/archive/2013/07/12/gcc_member_function_template.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[深入理解C++（二）]理解接口继承规则</title><link>http://www.cppblog.com/kesalin/archive/2012/11/06/interface_inherit.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Tue, 06 Nov 2012 13:21:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2012/11/06/interface_inherit.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/194777.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2012/11/06/interface_inherit.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/194777.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/194777.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在前一篇《[深入理解C++（一）]类型转换（Type Casting）》中，我详细讲述了 C++ 中转型动作，以及使用规则。有网友说应该提及下《深度探索 C++ 对象模型》一书中的内容，其实他的意思是，要是对 C++ 对象的内存布局不甚了解，就想要彻悟C++中的类型转型，对象切割，虚函数调用等，犹如脱离了坚实的根基，想去建空中阁楼。理解 C++ 对象的内存布局对学会 C++来说至关重要，但我不打算写 C++ 对象的内存布局相关的文章，因为要站在前人的肩膀上，大牛陈皓 已经就这个主题写了三篇图文并茂的文章：<br>（一），C++ 虚函数表解析<br>（二），C++ 对象的内存布局（上）<br>（三），C++ 对象的内存布局（下）<br> <br>在继续阅读本文之前，建议先阅读这三篇文章，以更好地理解本系列文章。在接下来的内容中，我将从重载，重写，屏蔽等概念入手，引入众多接口继承规则。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2012/11/06/interface_inherit.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/194777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2012-11-06 21:21 <a href="http://www.cppblog.com/kesalin/archive/2012/11/06/interface_inherit.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[深入理解C++（一）]类型转换（Type Casting）</title><link>http://www.cppblog.com/kesalin/archive/2012/10/28/type_cast.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Sun, 28 Oct 2012 13:44:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2012/10/28/type_cast.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/193986.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2012/10/28/type_cast.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/193986.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/193986.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 类型转换就是将给定类型的表达式转换为另一种类型。C++中的转型可分为两种：隐式类型转换和显式类型转换。下面将详细介绍这两种转型操作，以及各自的适用场景，潜在问题，最终将总结使用类型转换操作应牢记的原则。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2012/10/28/type_cast.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/193986.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2012-10-28 21:44 <a href="http://www.cppblog.com/kesalin/archive/2012/10/28/type_cast.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入分析Sleep(0)与Sleep(1)的区别</title><link>http://www.cppblog.com/kesalin/archive/2012/10/11/Sleep.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Thu, 11 Oct 2012 12:04:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2012/10/11/Sleep.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/193183.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2012/10/11/Sleep.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/193183.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/193183.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 当 timeout = 0， 即 Sleep(0)，如果线程调度器的可运行队列中有大于或等于当前线程优先级的就绪线程存在，操作系统会将当前线程从处理器上移除，调度其他优先级高的就绪线程运行；如果可运行队列中的没有就绪线程或所有就绪线程的优先级均低于当前线程优先级，那么当前线程会继续执行，就像没有调用 Sleep(0)一样。<br><br>当 timeout > 0 时，如：Sleep(1)，会引发线程上下文切换：调用线程会从线程调度器的可运行队列中被移除一段时间，这个时间段约等于 timeout 所指定的时间长度。为什么说约等于呢？是因为睡眠时间单位为毫秒，这与系统的时间精度有关。通常情况下，系统的时间精度为 10 ms，那么指定任意少于 10 ms但大于 0 ms 的睡眠时间，均会向上求值为 10 ms。&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2012/10/11/Sleep.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/193183.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2012-10-11 20:04 <a href="http://www.cppblog.com/kesalin/archive/2012/10/11/Sleep.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><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>【译】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>4</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>6</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>Head First design patterns读书笔记</title><link>http://www.cppblog.com/kesalin/archive/2008/07/20/56714.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Sun, 20 Jul 2008 15:31:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2008/07/20/56714.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/56714.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2008/07/20/56714.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/56714.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/56714.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Head First design patterns读书笔记&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2008/07/20/56714.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/56714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2008-07-20 23:31 <a href="http://www.cppblog.com/kesalin/archive/2008/07/20/56714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C语言声明的优先级规则</title><link>http://www.cppblog.com/kesalin/archive/2008/06/30/54992.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Mon, 30 Jun 2008 15:33:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2008/06/30/54992.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/54992.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2008/06/30/54992.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/54992.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/54992.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 《Expert C Programming》(《C专家编程》)中提到C语言声明的优先级规则如下：<br><br>A 声明从它的名字开始读取，然后按照优先级顺序依次读取；<br><br>B 优先级从高到低依次是：      <br><br>   B.1 声明中被括号括起来的那部分；     <br><br>   B.2 后缀操作符：括号()表示这是一个函数，而方括号[]表示这是一个数组；     <br><br>   B.3 前缀操作符：星号*标识“指向...的指针”；<br><br>C 如果const和(或者)volatile关键字的后面紧跟类型说明符(如int，long等)，那么它作用于类型说明符，在其他情况下，const和(或)volatile关键字作用于它左边紧邻的指针星号。<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2008/06/30/54992.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/54992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2008-06-30 23:33 <a href="http://www.cppblog.com/kesalin/archive/2008/06/30/54992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【译】在C++中使用LUA</title><link>http://www.cppblog.com/kesalin/archive/2008/06/17/53688.html</link><dc:creator>罗朝辉</dc:creator><author>罗朝辉</author><pubDate>Tue, 17 Jun 2008 04:38:00 GMT</pubDate><guid>http://www.cppblog.com/kesalin/archive/2008/06/17/53688.html</guid><wfw:comment>http://www.cppblog.com/kesalin/comments/53688.html</wfw:comment><comments>http://www.cppblog.com/kesalin/archive/2008/06/17/53688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/kesalin/comments/commentRss/53688.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/kesalin/services/trackbacks/53688.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要:                                           Using LUA with C++<br><br>原文链接：http://www.spheregames.com/index.php?p=templates/pages/tutorials<br><br>作者：http://www.spheregames.com<br><br>翻译：飘飘白云（http://www.cppblog.com/kesalin ）<br><br> <br><br>译注：翻译本文并未获得原作者的许可，翻译本文来仅供个人学习消遣，故谢却转载。<br><br>原文中的示例代码汲取了《游戏编程精粹 5》中Matthew Harmon写的 “Building LUA into Games”一文的想法与部分代码实现，我将“Building LUA into Games”一文的示例代码应用到最新的LUA版本，也打包贴在这里，供大家参考。<br><br>Using LUA with C++：示例代码下载<br><br>Building LUA into Gam&nbsp;&nbsp;<a href='http://www.cppblog.com/kesalin/archive/2008/06/17/53688.html'>阅读全文</a><img src ="http://www.cppblog.com/kesalin/aggbug/53688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/kesalin/" target="_blank">罗朝辉</a> 2008-06-17 12:38 <a href="http://www.cppblog.com/kesalin/archive/2008/06/17/53688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>