?!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> c++11中的move与forward-南软g开发|׃软g开?南赢dU技软g开发公?/title> <meta name="keywords" content="c++11中的move与forward"/> <meta name="description" content="一.move关于lvaue和rvalue,在c++11以前存在一个有的现象QT&指向lvalueQconstT&卛_以指向lvalue也可以指向rvalue?nbsp;但就是没有一U引用类型,可以限制为只指向rvalue. q乍h好像也不是很大问题,但事实上"/> <link href="/css/style.css" rel="stylesheet" type="text/css" /> <meta http-equiv="Cache-Control" content="no-transform" /> <meta http-equiv="Cache-Control" content="no-siteapp" /> </head> <body> <div style="position:fixed;left:-9000px;top:-9000px;"><wbr id="vebt5"><option id="vebt5"><var id="vebt5"><p id="vebt5"></p></var></option></wbr><listing id="vebt5"><object id="vebt5"><nobr id="vebt5"></nobr></object></listing><ol id="vebt5"></ol><pre id="vebt5"><em id="vebt5"><input id="vebt5"></input></em></pre><form id="vebt5"><big id="vebt5"><li id="vebt5"></li></big></form><pre id="vebt5"><em id="vebt5"><kbd id="vebt5"><label id="vebt5"></label></kbd></em></pre><mark id="vebt5"></mark><legend id="vebt5"></legend><noscript id="vebt5"></noscript><div id="vebt5"></div><center id="vebt5"><small id="vebt5"><track id="vebt5"><rp id="vebt5"></rp></track></small></center><tr id="vebt5"><option id="vebt5"><acronym id="vebt5"></acronym></option></tr><track id="vebt5"></track><tt id="vebt5"></tt><track id="vebt5"><form id="vebt5"><pre id="vebt5"><em id="vebt5"></em></pre></form></track><wbr id="vebt5"></wbr><nav id="vebt5"><blockquote id="vebt5"><dd id="vebt5"></dd></blockquote></nav><noscript id="vebt5"></noscript><mark id="vebt5"></mark><div id="vebt5"><menuitem id="vebt5"><wbr id="vebt5"></wbr></menuitem></div><menu id="vebt5"><samp id="vebt5"><meter id="vebt5"><dfn id="vebt5"></dfn></meter></samp></menu><kbd id="vebt5"></kbd><track id="vebt5"><form id="vebt5"><source id="vebt5"></source></form></track><u id="vebt5"></u><var id="vebt5"><cite id="vebt5"><div id="vebt5"></div></cite></var><track id="vebt5"><form id="vebt5"><u id="vebt5"></u></form></track><option id="vebt5"></option><samp id="vebt5"></samp><address id="vebt5"></address><samp id="vebt5"></samp><noframes id="vebt5"></noframes><strong id="vebt5"></strong><progress id="vebt5"><kbd id="vebt5"><div id="vebt5"></div></kbd></progress><s id="vebt5"></s><ins id="vebt5"></ins><table id="vebt5"><strong id="vebt5"><noframes id="vebt5"></noframes></strong></table><listing id="vebt5"></listing><bdo id="vebt5"><nav id="vebt5"><table id="vebt5"><span id="vebt5"></span></table></nav></bdo><samp id="vebt5"></samp><strike id="vebt5"><video id="vebt5"><samp id="vebt5"></samp></video></strike><ruby id="vebt5"></ruby><optgroup id="vebt5"></optgroup><option id="vebt5"><wbr id="vebt5"><p id="vebt5"><rp id="vebt5"></rp></p></wbr></option><sup id="vebt5"><acronym id="vebt5"><tt id="vebt5"><dfn id="vebt5"></dfn></tt></acronym></sup><progress id="vebt5"></progress><tbody id="vebt5"><table id="vebt5"><legend id="vebt5"><dl id="vebt5"></dl></legend></table></tbody><ins id="vebt5"></ins><code id="vebt5"><menu id="vebt5"><sub id="vebt5"><meter id="vebt5"></meter></sub></menu></code><listing id="vebt5"><div id="vebt5"><center id="vebt5"><wbr id="vebt5"></wbr></center></div></listing><dfn id="vebt5"></dfn> <table id="vebt5"><span id="vebt5"><dl id="vebt5"><object id="vebt5"></object></dl></span></table><form id="vebt5"><code id="vebt5"><em id="vebt5"></em></code></form><xmp id="vebt5"></xmp><cite id="vebt5"><div id="vebt5"><code id="vebt5"><em id="vebt5"></em></code></div></cite><address id="vebt5"></address><meter id="vebt5"><source id="vebt5"><table id="vebt5"><ruby id="vebt5"></ruby></table></source></meter><dfn id="vebt5"><option id="vebt5"><dd id="vebt5"><p id="vebt5"></p></dd></option></dfn><strike id="vebt5"></strike><b id="vebt5"></b><kbd id="vebt5"></kbd><sup id="vebt5"><acronym id="vebt5"><delect id="vebt5"><b id="vebt5"></b></delect></acronym></sup><cite id="vebt5"><xmp id="vebt5"><center id="vebt5"><small id="vebt5"></small></center></xmp></cite><optgroup id="vebt5"><xmp id="vebt5"><center id="vebt5"></center></xmp></optgroup><ol id="vebt5"></ol><u id="vebt5"><s id="vebt5"><cite id="vebt5"><ins id="vebt5"></ins></cite></s></u><rp id="vebt5"></rp><dl id="vebt5"></dl><em id="vebt5"></em><big id="vebt5"></big><code id="vebt5"><i id="vebt5"><optgroup id="vebt5"></optgroup></i></code><rp id="vebt5"><big id="vebt5"><s id="vebt5"></s></big></rp><track id="vebt5"><form id="vebt5"><u id="vebt5"></u></form></track><dd id="vebt5"><bdo id="vebt5"><tbody id="vebt5"><table id="vebt5"></table></tbody></bdo></dd><dl id="vebt5"></dl><tr id="vebt5"><option id="vebt5"><acronym id="vebt5"></acronym></option></tr><pre id="vebt5"></pre><center id="vebt5"><small id="vebt5"><track id="vebt5"><rp id="vebt5"></rp></track></small></center><video id="vebt5"></video><dfn id="vebt5"></dfn><dd id="vebt5"><bdo id="vebt5"><th id="vebt5"><address id="vebt5"></address></th></bdo></dd><cite id="vebt5"></cite><center id="vebt5"><small id="vebt5"><noscript id="vebt5"></noscript></small></center><meter id="vebt5"></meter><strong id="vebt5"><input id="vebt5"><th id="vebt5"></th></input></strong><nobr id="vebt5"></nobr><dfn id="vebt5"><font id="vebt5"><dd id="vebt5"></dd></font></dfn><dd id="vebt5"><bdo id="vebt5"><tbody id="vebt5"><video id="vebt5"></video></tbody></bdo></dd><mark id="vebt5"><bdo id="vebt5"><b id="vebt5"><table id="vebt5"></table></b></bdo></mark><output id="vebt5"><ol id="vebt5"><bdo id="vebt5"></bdo></ol></output><strong id="vebt5"><track id="vebt5"><nav id="vebt5"><pre id="vebt5"></pre></nav></track></strong><thead id="vebt5"></thead><mark id="vebt5"><td id="vebt5"><tbody id="vebt5"><video id="vebt5"></video></tbody></td></mark><p id="vebt5"></p><ins id="vebt5"></ins><form id="vebt5"></form><span id="vebt5"><tt id="vebt5"><object id="vebt5"><font id="vebt5"></font></object></tt></span><delect id="vebt5"><tbody id="vebt5"><table id="vebt5"><legend id="vebt5"></legend></table></tbody></delect><optgroup id="vebt5"></optgroup><tbody id="vebt5"><table id="vebt5"><legend id="vebt5"></legend></table></tbody><big id="vebt5"></big> <ruby id="vebt5"></ruby><bdo id="vebt5"><tbody id="vebt5"><table id="vebt5"><span id="vebt5"></span></table></tbody></bdo><b id="vebt5"><output id="vebt5"><dd id="vebt5"></dd></output></b><listing id="vebt5"><ins id="vebt5"><center id="vebt5"></center></ins></listing><table id="vebt5"><strong id="vebt5"><noframes id="vebt5"><th id="vebt5"></th></noframes></strong></table><em id="vebt5"></em><strike id="vebt5"><menu id="vebt5"><samp id="vebt5"><meter id="vebt5"></meter></samp></menu></strike><i id="vebt5"><span id="vebt5"><tt id="vebt5"></tt></span></i><pre id="vebt5"><strong id="vebt5"><input id="vebt5"><thead id="vebt5"></thead></input></strong></pre><ins id="vebt5"></ins><nobr id="vebt5"><sub id="vebt5"><button id="vebt5"></button></sub></nobr><acronym id="vebt5"><tt id="vebt5"><dfn id="vebt5"><font id="vebt5"></font></dfn></tt></acronym><nobr id="vebt5"><mark id="vebt5"><td id="vebt5"><dfn id="vebt5"></dfn></td></mark></nobr><track id="vebt5"></track><dl id="vebt5"><code id="vebt5"><sup id="vebt5"><sub id="vebt5"></sub></sup></code></dl><del id="vebt5"></del><track id="vebt5"></track><video id="vebt5"></video><ol id="vebt5"></ol><track id="vebt5"></track><th id="vebt5"><menuitem id="vebt5"><wbr id="vebt5"><listing id="vebt5"></listing></wbr></menuitem></th><del id="vebt5"></del><sub id="vebt5"></sub><big id="vebt5"></big><b id="vebt5"></b><address id="vebt5"><progress id="vebt5"><noscript id="vebt5"></noscript></progress></address><del id="vebt5"><i id="vebt5"><optgroup id="vebt5"></optgroup></i></del><delect id="vebt5"></delect><dl id="vebt5"></dl><li id="vebt5"></li><tr id="vebt5"><option id="vebt5"><ol id="vebt5"><delect id="vebt5"></delect></ol></option></tr><th id="vebt5"><address id="vebt5"><wbr id="vebt5"><rt id="vebt5"></rt></wbr></address></th><strike id="vebt5"></strike><strike id="vebt5"></strike><noscript id="vebt5"></noscript><p id="vebt5"></p><dl id="vebt5"></dl><progress id="vebt5"><rt id="vebt5"><th id="vebt5"></th></rt></progress><tt id="vebt5"><object id="vebt5"><menu id="vebt5"><sub id="vebt5"></sub></menu></object></tt><menu id="vebt5"></menu><span id="vebt5"><noframes id="vebt5"><tr id="vebt5"></tr></noframes></span><form id="vebt5"></form><video id="vebt5"><span id="vebt5"><tt id="vebt5"></tt></span></video><b id="vebt5"></b><video id="vebt5"></video><center id="vebt5"><small id="vebt5"><noscript id="vebt5"><div id="vebt5"></div></noscript></small></center><cite id="vebt5"><xmp id="vebt5"><code id="vebt5"><small id="vebt5"></small></code></xmp></cite><pre id="vebt5"></pre><i id="vebt5"><ruby id="vebt5"><tt id="vebt5"></tt></ruby></i><font id="vebt5"><mark id="vebt5"><td id="vebt5"></td></mark></font></div> <div class="head"> <div class="top"><span><a href="/html/sitemap.xml">XML</a> | <a href="/html/sitemap.html">HTML</a> | <a href="/sitemap.txt">TXT</a></span></div> <div class="bank"> <div class="logo"> <h1><strong><a href="http://www.cabanatime.com" style="margin-right:10px">南软g开?/a></strong><strong><a href="http://www.cabanatime.com">׃软g开?/a></strong></h1> </div> <div class="contact-top"></div> </div> <div class="menu"> <ul> <li><a href="/">?#160;   ?/a></li> <li><a href="/About/">关于我们</a></li> <li><a href="/Advantage/">开发优?/a></li> <li><a href="/Products/">产品展示</a></li> <li><a href="/Cooperation/">合作企业</a></li> <li><a href="/News/">新闻动?/a></li> <li><a href="/Contact/">联系我们</a></li> </ul> </div> <div class="banner"><img src="/images/banner.jpg" width="1000" height="341"/></div> </div> <div id="position"><div>您当前位|:<a href="/">软g开?/a> >> <a href="/News/">新闻动?/a> >> <a href="/News/Technology/">软g开发技?/a> >> 览文章</div></div> <div class="youshi_f1" id="youshi_tdyx"> <div class="youshi01"> <h1 class="article_title">c++11中的move与forward</h1> <div class="article_author">d旉Q?016-12-20 17:10:14 文章作者:<a href="/">南软g开?/a> 览ơ数Q?Script Language="Javascript" Src="/item/GetHits.asp?Action=Count&GetFlag=0&m=1&ID=3063"></Script></div> <div class="article_main"><div id="MyContent"><p style="margin-top: 0px; margin-bottom: 0px; padding: 15px 0px 0px; line-height: 30px; font-family: 宋体; color: rgb(51, 51, 51); font-size: 13.3333px; white-space: normal; background-color: rgb(241, 241, 241);"><strong style="margin: 0px; padding: 0px;">一. move</strong></p><p>关于lvaue和rvalue, 在c++11以前存在一个有的现象QT& 指向lvalueQ?const T&卛_以指向lvalue也可以指向rvalue?/p><p> </p><p>但就是没有一U引用类型,可以限制为只指向rvalue.</p><p> </p><p>q乍h好像也不是很大问题,但事实上q个~陷在有些时候严重的限制了我们在某些情况下,写出更有效率的代码?/p><p> </p><p>举个_子Q假设我们有一个类Q它包含了一些资源:</p><p> </p><p>复制代码</p><p>class holder</p><p>{</p><p>     public:</p><p> </p><p>          holder()</p><p>          {</p><p>               resource_ = new Resource();</p><p>          }</p><p>          ~holder()</p><p>          {</p><p>               delete resource_;</p><p>          }</p><p> </p><p>          holder(const holder& other)</p><p>          {</p><p>                resource_ = new Resource(*other.resource_);</p><p>          }</p><p> </p><p>          holder(holder& other)</p><p>          {</p><p>                resource_ = new Resource(*other.resource_);</p><p>          }</p><p> </p><p>          holder& operator=(const holder& other)</p><p>          {</p><p>                delete resource_;</p><p>                resource_ = new Resource(*other.resource_);</p><p>                return *this;</p><p>          }</p><p>           holder& operator=(holder& other)</p><p>          {</p><p>                delete resource_;</p><p>                resource_ = new Resource(*other.resource_);</p><p>                return *this;</p><p>          }</p><p>          private:</p><p> </p><p>               Resource* resource_;</p><p>};</p><p>复制代码</p><p> </p><p> </p><p>q是个RAII的类Q构造函C析构函数分别负责资源的获取与释放Q因此也相应处理了拷贝构造函?copy constructor)和重载赋值操作符(assignment operator)?/p><p> </p><p>现在假设我们q样来用这个类?/p><p> </p><p>// 假设存在如一个函敎ͼq回gؓholdercd</p><p>holder get_holder();</p><p> </p><p>holder h;</p><p> </p><p>h = get_holder();</p><p>q小D代码的最后一条语句做?件事情:</p><p> </p><p>1) 销毁h中的资源?/p><p> </p><p>2) Lget_holder()q回的资源?/p><p> </p><p>3) 销毁get_holder()q回的资源?/p><p> </p><p>我们昄可以发现q其中做了些不是很有必要的事情,假如我们可以直接交换h中的资源与get_holder()q回的资源,那这h们可以直接省掉第二步中的拯动作了?/p><p> </p><p>而这里之所以交换能辑ֈ相同的效果,是因为get_holder()q回的是临时的变量,是个rvalueQ它的生命周期通常来说很短Q具体在q里Q就是赋D句完成之后,M人都没法再引用该rvalueQ它马上p被销毁了?/p><p> </p><p>如果是像下面q样的用法,我们昄不可以直接交换两者的资源Q?/p><p> </p><p>holder h1;</p><p>holder h2;</p><p> </p><p>h1 = h2;</p><p>因ؓh2是个lvalueQ它的生命周期较长,在赋D句结束之后,变量q要存在Q还有可能要被别的地方用?/p><p> </p><p>昄Qrvalue的短生命周期l我们提供了在某些情况优化代码的可能?/p><p> </p><p>但这U可能在c++11以前是没法利用到的,因ؓQ我们没法在代码中对rvalue区别对待Q在函数体中Q无法分辨传q来的参数到底是不是rvalueQ缺一个rvalue的标记?/p><p> </p><p>回忆一?T& 指向的是lvalueQ而const T&指向的,却可能是lvalue或rvalueQ没法区分!</p><p> </p><p>Z解决q个问题Qc++11中引入了一个新的引用类型:T&&</p><p> </p><p>q种引用指向的变量是个rvalueQ?有了q个引用cdQ我们前面提到的问题p刃而解了?/p><p> </p><p>复制代码</p><p>class holder</p><p>{</p><p>     public:</p><p> </p><p>          holder()</p><p>          {</p><p>               resource_ = new Resource();</p><p>          }</p><p>          ~holder()</p><p>          {</p><p>               if (resource_) delete resource_;</p><p>          }</p><p> </p><p>          holder(const holder& other)</p><p>          {</p><p>                resource_ = new Resource(*other.resource_);</p><p>          }</p><p> </p><p>          holder(holder& other)</p><p>          {</p><p>                resource_ = new Resource(*other.resource_);</p><p>          }</p><p>          </p><p>          holder(holder&& other)</p><p>          {</p><p>                resource_ = other.resource_;</p><p>                other.resource_ = NULL;</p><p>          }</p><p> </p><p>          holder& operator=(const holder& other)</p><p>          {</p><p>                delete resource_;</p><p>                resource_ = new Resource(*other.resource_);</p><p>          return *this;</p><p>          }</p><p> </p><p>          holder& operator=(holder& other)</p><p>          {</p><p>                delete resource_;</p><p>                resource_ = new Resource(*other.resource_);</p><p>                return *this;</p><p>          }</p><p> </p><p>          holder& operator=(holder&& other)</p><p>          {</p><p>                std::swap(resource_, other.resource_);</p><p>                return *this;</p><p>          }</p><p> </p><p>          private:</p><p> </p><p>               Resource* resource_;</p><p>};    </p><p>复制代码</p><p>q时我们再写如下代码的时候:</p><p> </p><p>holder h1;</p><p>holder h2;</p><p> </p><p>h1 = h2; //调用operator(holder&);</p><p>h1 = get_holder(); //调用operator(holder&&)</p><p>昄后面的实现是更高效的?/p><p> </p><p> </p><p> </p><p>写到里,有的Z许提出问? T&& ref 指向的是叛_|那ref本n是左D是右|具体来说是Q?/p><p> </p><p>1 holder& operator=(holder&& other)</p><p>2 {</p><p>3      holder h = other;//q里调用的是operator=(holder&) q是operator=(holder&&)?</p><p>4      return *this;</p><p>5 }</p><p>q个问题的本质还是怎么区分rvalueQ?/p><p> </p><p>c++11中对rvalue作了明确的定义:</p><p> </p><p>Things that are declared as rvalue reference can be lvalues or rvalues. The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue.</p><p>如果一个变量有名字Q它是lvalue,否则Q它是rvalue?/p><p> </p><p>Ҏq样的定义,上面的问题中Qother是有名字的变量,因此是个lvalue,因此W?行调用的是operator=(holder&).</p><p> </p><p> </p><p> </p><p>好了说这么久Q一直没说到move()Q现在我们来l出定义Q?/p><p> </p><p>c++11中的move()是这样一个函敎ͼ它接受一个参敎ͼ然后q回一个该参数对应的rvalue().</p><p>p么简单!你甚臛_以暂时想像它的原型是q样?当然是错的,正确的原型我们后面再?</p><p> </p><p>T&& move(T& val);</p><p> </p><p> </p><p>那么Q这样一个move()Q它有什么用呢Q用处大了!</p><p> </p><p>前面用到了std::swap()q个函数Q回想一下以前我们是怎么x实现swap的呢Q?/p><p> </p><p>1 void swap(T& a, T& b)</p><p>2 {</p><p>3     T tmp = a;</p><p>4     a = b;</p><p>5     b = tmp;</p><p>6 }</p><p>惛_一下,如果T是我们之前定义的holderQ这里面多做了多无用功啊,每一个赋D句,有一ơ资源销毁,以及一ơ拷贝!但如果用上了move().</p><p> </p><p>1 void swap(T& a, T& b)</p><p>2 {</p><p>3     T tmp=move(a);</p><p>4     a = move(b);</p><p>5     b = move(tmp);</p><p>6 }</p><p>q样一来,如果holder提供了operator=(T&&)重蝲, 上述操作完全只是交换了3ơ指针,效率大大提升Q?/p><p> </p><p>move使得E序员在有需要的情况下,能够把lvalue当成rvalue来用?/p><p> </p><p> </p><p> </p><p><strong style="margin: 0px; padding: 0px;">? forward()</strong></p><p>1.转发问题</p><p>除了move()语义之外Qrvalue的提Z解决另一个问题:转发(forward).</p><p> </p><p>假设我们有这样一个模板函敎ͼ它的作用是:~存一些objectQ必要的时候,创徏新的?/p><p> </p><p>复制代码</p><p>template<class TYPE, class ARG></p><p>TYPE* acquire_obj(ARG arg)</p><p>{</p><p>     static list<TYPE*> caches;</p><p>     TYPE* ret;</p><p> </p><p>     if (!caches.empty())</p><p>     {</p><p>          ret = caches.pop_back();</p><p>          ret->reset(arg);</p><p>          return ret;</p><p>     }</p><p> </p><p>     ret = new TYPE(arg);</p><p>     return ret;</p><p>}</p><p>复制代码</p><p>q个模板函数的作用简单来_是转发一下参数arglTYPE的reset()函数和构造函敎ͼ除此它就没有再干别的事情Q在q个函数当中Q我们用了g递的方式来传递参敎ͼ昄是比较低效的Q多了次无必要的拯?/p><p> </p><p>于是我们准备Ҏ传递引用的方式Q同时考虑到要能接受rvalue作ؓ参数Q于是改成这P</p><p> </p><p>template<class TYPE, class ARG></p><p>TYPE* acquire_obj(const ARG& arg)</p><p>{</p><p>    //...</p><p>}</p><p>q样写其实很不灵z:</p><p> </p><p>1)首行Q如果reset() 或TYPE的构造函C接受constcd的引用,那上q的函数׃能用了Q必d外提供非const TYPE&的版本,参数一多的话,很麻烦?/p><p> </p><p>2)其次Q如果reset()或TYPE的构造函数能够接受rvalue作ؓ参数的话Q这个特性在acquire_obj()里头永远也用不上?/p><p> </p><p> </p><p> </p><p>其中1)好理解,2)是什么意思?</p><p> </p><p>2)说的是这L问题Q即使TYPE存在TYPE(TYPE&& other)q样的构造函敎ͼ它在acquire_obj()中也永远不会被调用,原因是在acquire_obj中,传递给TYPE构造函数的Q永q是lvalue.</p><p> </p><p>哪怕外面调用acquire_obj()Ӟ传递的是rvalue?/p><p> </p><p>holder get_holder();</p><p> </p><p>holder* h = acquire_obj<holder, holder>(get_holder());</p><p>虽然在上面的代码中,我们传递给acquire_obj的是一个rvalueQ但是在acuire_obj内部Q我们再使用q个参数Ӟ它却永远是lvalueQ因为它有名字?/p><p> </p><p>acquire_objq个函数它的基本功能只是传发一下参敎ͼ理想状况下它不应该改变我们传递参数的cdQ假如我们传l它lvalue,它就应该传lvaluelTYPEQ假如我们传rvaluel它Q它应该传rvaluelTYPEQ但上面的写法却没有做到q点Q而在c++11以前也没法做到?/p><p> </p><p>forward()函数的出玎ͼ是Z解决q个问题?/p><p> </p><p>forward()函数的作用:它接受一个参敎ͼ然后q回该参数本来所对应的类型?/p><p>比如说在上述的例子中(暂时省略参数的原?后面再介l?:</p><p> </p><p>复制代码</p><p>holder* h = acquire_obj<holder, holder>(get_holder());</p><p>//假设 acquire_obj()接受了一个rvalue作ؓ参数Q在它的内部Q?/p><p>TYPE* acquire_obj(arg)</p><p>{</p><p>    //arg本来是rvalueQ如果我们直接引用,它会被当成lvalue来用?/p><p>    //但如果我们用forward()处理一下,我们却可以得到它的rvalue版本?/p><p>    //此处 TYPE的构造函数接受的是一个rvalue?/p><p>    TYPE* ret = new TYPE(forward(arg));</p><p>}</p><p> </p><p>//但如果我们传lacquire_obj()的是一个lvalueQ?/p><p>holder h1;</p><p>//acquire_obj接受了lvalue作ؓ参数?/p><p>acquire_obj<holder,holder>(h1);</p><p> </p><p>TYPE* acquire_obj(arg)</p><p>{</p><p>    //此处,TYPE的构造函数接受的是一个lvalue?/p><p>    TYPE* ret = new TYPE(forward(arg));</p><p>}</p><p>复制代码</p><p> </p><p> </p><p>2. 二个原则</p><p>要理解forward()是怎么实现的,先得说说c++11中关于引用的二个原则?/p><p> </p><p>原则(1):</p><p> </p><p>引用折叠原则(reference collapsing rule)</p><p> </p><p>1) T& &(引用的引? 被{化成 T&.</p><p> </p><p>2QT&& &(rvalue的引用)被传化成 T&.</p><p> </p><p>3)  T& &&(引用作rvalue) 被{化成 T&.</p><p> </p><p>4)  T&& && 被{化成 T&&.</p><p> </p><p> </p><p> </p><p>原则(2):</p><p> </p><p>对于以rvalue reference作ؓ参数的模板函敎ͼ它的参数推导也有一个特D的原则:</p><p> </p><p>假设函数原型为:</p><p> </p><p>template<class TYPE, class ARG></p><p>TYPE* acquire_obj(ARG&& arg);</p><p>1)如果我们传递lvaluelacquire_obj(), ARG׃被推gؓARG&Q因?/p><p> </p><p>复制代码</p><p>ARG arg;</p><p> </p><p>acquire_obj(arg)中acquire_obj被推gؓ</p><p>acquire_obj(ARG& &&)</p><p>Ҏ前面说的折叠原则Qacquire_obj(ARG& &&)</p><p>最后变?/p><p>acquire_obj(ARG&)</p><p>复制代码</p><p>2)如果我们传递rvaluelacquire_obj(),ARG׃被推gؓARG,因此</p><p> </p><p>acquire_obj(get_arg());</p><p>则acquire_obj 被推gؓ acquire_obj(ARG&&)</p><p> </p><p> </p><p>3.l论</p><p>有了q两个原则,现在我们可以l出最后acquire_obj的原型,以及forward()的原型?/p><p> </p><p>复制代码</p><p>template<class TYPE></p><p>TYPE&& forward(typename remove_reference<TYPE>::type& arg)</p><p>{</p><p>   return static_cast<TYPE&&>(arg);</p><p>}</p><p> </p><p>template<class TYPE, class ARG></p><p>TYPE* acquire_obj(ARG&& arg)</p><p>{</p><p>   return new TYPE(forward<ARG>(arg));</p><p>}</p><p>复制代码</p><p> </p><p> </p><p>下面我们验证一下,上述函数是否能正常工作,假如我们传给acquire_obj一个lvalueQ根据上面说的模板推导原则,ARG会被推导为ARG&,我们得到如下函数Q?/p><p> </p><p>复制代码</p><p>TYPE* acquire_obj(ARG& && arg)</p><p>{</p><p>   return new TYPE(forward<ARG&>(arg));</p><p>}</p><p> </p><p>以及相应的forward()函数?/p><p> </p><p>TYPE& && </p><p>forward(typename remove_reference<TYPE&>::type& arg)</p><p>{</p><p>   return static_cast<TYPE& &&>(arg);</p><p>}</p><p> </p><p>再根据折叠原则,我们得到如下的函敎ͼ</p><p>TYPE* acquire_obj(ARG& arg)</p><p>{</p><p>   return new TYPE(forward<ARG&>(arg));</p><p>}</p><p> </p><p>以及相应的forward()函数?/p><p> </p><p>TYPE& </p><p>forward(typename remove_reference<TYPE&>::type& arg)</p><p>{</p><p>   return static_cast<TYPE&>(arg);</p><p>}</p><p>复制代码</p><p> </p><p> </p><p> 所以,最后在acquire_obj中,forwardq回了一个lvalue, TYPE的构造函数接受了一个lvaue, q正是我们所惌的?/p><p> </p><p> 而假如我们传递给acquire_obj一个rvalue的参敎ͼҎ模板推导原则Q我们知道ARG会被推导为ARGQ于是得到如下函敎ͼ</p><p> </p><p> </p><p> </p><p>复制代码</p><p>TYPE* acquire_obj(ARG&& arg)</p><p>{</p><p>   return new TYPE(forward<ARG>(arg));</p><p>}</p><p> </p><p>以及相应的forward()函数?/p><p> </p><p>TYPE&& </p><p>forward(typename remove_reference<TYPE>::type& arg)</p><p>{</p><p>   return static_cast<TYPE&&>(arg);</p><p>}</p><p>复制代码</p><p>最后acquire_obj中forward()q回了一个rvalueQTYPE的构造函数接受了一个rvalueQ也是我们所惌的?/p><p> </p><p>可见Q上面的设计完成了我们所惌的功能,q时的acquire_obj函数才是完美的{发函数?/p><p> </p><p> </p><p> </p><p><strong style="margin: 0px; padding: 0px;">?move的原?/strong></p><p> </p><p> </p><p>复制代码</p><p>template<class T> </p><p>typename remove_reference<T>::type&&</p><p>std::move(T&& a)</p><p>{</p><p>  typedef typename remove_reference<T>::type&& RvalRef;</p><p>  return static_cast<RvalRef>(a);</p><p>} </p><p>复制代码</p><p>Ҏrvalue引用的模板推导原则和折叠原则Q我们很Ҏ验证Q无论是lmove传递了一个lvalueq是rvalueQ最l返回的Q都是一个rvalue reference.</p><p> </p><p>而这正是move的意义,得到一个rvalue的引用?/p><p> </p><p> </p><p> </p><p>看到q里有h也许会发玎ͼ其实是一个cast嘛,实是这P直接用static_cast也是能达到同L效果Q只是move更具语义|了?/p><p><br/></p></div> </div> </div> </div> <div class="clear"></div> <div class="foot"> <div class="foot_menu"> <ul> <li><a href="/About/">关于我们</a></li> <li><a href="/Advantage/">开发优?/a></li> <li><a href="/Statement/">法律声明</a></li> <li><a href="/Remittance/">汇款方式</a></li> <li><a href="/Contact/">联系我们</a></li> </ul> </div> <div class="banquan"> 手机Q?8678812288 EQMail:1069706080@qq.com<br /> 地址Q山东省南市舜耕\泉城公园东门园内向北50c? 鲁ICP?7011972? 版权所?008Q?013 ׃赢d信息U技有限公司<script type="text/javascript"> var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://"); document.write(unescape("%3Cscript src='" + _bdhmProtocol + "#/h.js%3F5fbc066dba9928a1e914c338c6945c98' type='text/javascript'%3E%3C/script%3E")); </script> </div> </div> <div style="position:fixed;left:-9000px;top:-9000px;"><wbr id="vebt5"><option id="vebt5"><var id="vebt5"><p id="vebt5"></p></var></option></wbr><listing id="vebt5"><object id="vebt5"><nobr id="vebt5"></nobr></object></listing><ol id="vebt5"></ol><pre id="vebt5"><em id="vebt5"><input id="vebt5"></input></em></pre><form id="vebt5"><big id="vebt5"><li id="vebt5"></li></big></form><pre id="vebt5"><em id="vebt5"><kbd id="vebt5"><label id="vebt5"></label></kbd></em></pre><mark id="vebt5"></mark><legend id="vebt5"></legend><noscript id="vebt5"></noscript><div id="vebt5"></div><center id="vebt5"><small id="vebt5"><track id="vebt5"><rp id="vebt5"></rp></track></small></center><tr id="vebt5"><option id="vebt5"><acronym id="vebt5"></acronym></option></tr><track id="vebt5"></track><tt id="vebt5"></tt><track id="vebt5"><form id="vebt5"><pre id="vebt5"><em id="vebt5"></em></pre></form></track><wbr id="vebt5"></wbr><nav id="vebt5"><blockquote id="vebt5"><dd id="vebt5"></dd></blockquote></nav><noscript id="vebt5"></noscript><mark id="vebt5"></mark><div id="vebt5"><menuitem id="vebt5"><wbr id="vebt5"></wbr></menuitem></div><menu id="vebt5"><samp id="vebt5"><meter id="vebt5"><dfn id="vebt5"></dfn></meter></samp></menu><kbd id="vebt5"></kbd><track id="vebt5"><form id="vebt5"><source id="vebt5"></source></form></track><u id="vebt5"></u><var id="vebt5"><cite id="vebt5"><div id="vebt5"></div></cite></var><track id="vebt5"><form id="vebt5"><u id="vebt5"></u></form></track><option id="vebt5"></option><samp id="vebt5"></samp><address id="vebt5"></address><samp id="vebt5"></samp><noframes id="vebt5"></noframes><strong id="vebt5"></strong><progress id="vebt5"><kbd id="vebt5"><div id="vebt5"></div></kbd></progress><s id="vebt5"></s><ins id="vebt5"></ins><table id="vebt5"><strong id="vebt5"><noframes id="vebt5"></noframes></strong></table><listing id="vebt5"></listing><bdo id="vebt5"><nav id="vebt5"><table id="vebt5"><span id="vebt5"></span></table></nav></bdo><samp id="vebt5"></samp><strike id="vebt5"><video id="vebt5"><samp id="vebt5"></samp></video></strike><ruby id="vebt5"></ruby><optgroup id="vebt5"></optgroup><option id="vebt5"><wbr id="vebt5"><p id="vebt5"><rp id="vebt5"></rp></p></wbr></option><sup id="vebt5"><acronym id="vebt5"><tt id="vebt5"><dfn id="vebt5"></dfn></tt></acronym></sup><progress id="vebt5"></progress><tbody id="vebt5"><table id="vebt5"><legend id="vebt5"><dl id="vebt5"></dl></legend></table></tbody><ins id="vebt5"></ins><code id="vebt5"><menu id="vebt5"><sub id="vebt5"><meter id="vebt5"></meter></sub></menu></code><listing id="vebt5"><div id="vebt5"><center id="vebt5"><wbr id="vebt5"></wbr></center></div></listing><dfn id="vebt5"></dfn> <table id="vebt5"><span id="vebt5"><dl id="vebt5"><object id="vebt5"></object></dl></span></table><form id="vebt5"><code id="vebt5"><em id="vebt5"></em></code></form><xmp id="vebt5"></xmp><cite id="vebt5"><div id="vebt5"><code id="vebt5"><em id="vebt5"></em></code></div></cite><address id="vebt5"></address><meter id="vebt5"><source id="vebt5"><table id="vebt5"><ruby id="vebt5"></ruby></table></source></meter><dfn id="vebt5"><option id="vebt5"><dd id="vebt5"><p id="vebt5"></p></dd></option></dfn><strike id="vebt5"></strike><b id="vebt5"></b><kbd id="vebt5"></kbd><sup id="vebt5"><acronym id="vebt5"><delect id="vebt5"><b id="vebt5"></b></delect></acronym></sup><cite id="vebt5"><xmp id="vebt5"><center id="vebt5"><small id="vebt5"></small></center></xmp></cite><optgroup id="vebt5"><xmp id="vebt5"><center id="vebt5"></center></xmp></optgroup><ol id="vebt5"></ol><u id="vebt5"><s id="vebt5"><cite id="vebt5"><ins id="vebt5"></ins></cite></s></u><rp id="vebt5"></rp><dl id="vebt5"></dl><em id="vebt5"></em><big id="vebt5"></big><code id="vebt5"><i id="vebt5"><optgroup id="vebt5"></optgroup></i></code><rp id="vebt5"><big id="vebt5"><s id="vebt5"></s></big></rp><track id="vebt5"><form id="vebt5"><u id="vebt5"></u></form></track><dd id="vebt5"><bdo id="vebt5"><tbody id="vebt5"><table id="vebt5"></table></tbody></bdo></dd><dl id="vebt5"></dl><tr id="vebt5"><option id="vebt5"><acronym id="vebt5"></acronym></option></tr><pre id="vebt5"></pre><center id="vebt5"><small id="vebt5"><track id="vebt5"><rp id="vebt5"></rp></track></small></center><video id="vebt5"></video><dfn id="vebt5"></dfn><dd id="vebt5"><bdo id="vebt5"><th id="vebt5"><address id="vebt5"></address></th></bdo></dd><cite id="vebt5"></cite><center id="vebt5"><small id="vebt5"><noscript id="vebt5"></noscript></small></center><meter id="vebt5"></meter><strong id="vebt5"><input id="vebt5"><th id="vebt5"></th></input></strong><nobr id="vebt5"></nobr><dfn id="vebt5"><font id="vebt5"><dd id="vebt5"></dd></font></dfn><dd id="vebt5"><bdo id="vebt5"><tbody id="vebt5"><video id="vebt5"></video></tbody></bdo></dd><mark id="vebt5"><bdo id="vebt5"><b id="vebt5"><table id="vebt5"></table></b></bdo></mark><output id="vebt5"><ol id="vebt5"><bdo id="vebt5"></bdo></ol></output><strong id="vebt5"><track id="vebt5"><nav id="vebt5"><pre id="vebt5"></pre></nav></track></strong><thead id="vebt5"></thead><mark id="vebt5"><td id="vebt5"><tbody id="vebt5"><video id="vebt5"></video></tbody></td></mark><p id="vebt5"></p><ins id="vebt5"></ins><form id="vebt5"></form><span id="vebt5"><tt id="vebt5"><object id="vebt5"><font id="vebt5"></font></object></tt></span><delect id="vebt5"><tbody id="vebt5"><table id="vebt5"><legend id="vebt5"></legend></table></tbody></delect><optgroup id="vebt5"></optgroup><tbody id="vebt5"><table id="vebt5"><legend id="vebt5"></legend></table></tbody><big id="vebt5"></big> <ruby id="vebt5"></ruby><bdo id="vebt5"><tbody id="vebt5"><table id="vebt5"><span id="vebt5"></span></table></tbody></bdo><b id="vebt5"><output id="vebt5"><dd id="vebt5"></dd></output></b><listing id="vebt5"><ins id="vebt5"><center id="vebt5"></center></ins></listing><table id="vebt5"><strong id="vebt5"><noframes id="vebt5"><th id="vebt5"></th></noframes></strong></table><em id="vebt5"></em><strike id="vebt5"><menu id="vebt5"><samp id="vebt5"><meter id="vebt5"></meter></samp></menu></strike><i id="vebt5"><span id="vebt5"><tt id="vebt5"></tt></span></i><pre id="vebt5"><strong id="vebt5"><input id="vebt5"><thead id="vebt5"></thead></input></strong></pre><ins id="vebt5"></ins><nobr id="vebt5"><sub id="vebt5"><button id="vebt5"></button></sub></nobr><acronym id="vebt5"><tt id="vebt5"><dfn id="vebt5"><font id="vebt5"></font></dfn></tt></acronym><nobr id="vebt5"><mark id="vebt5"><td id="vebt5"><dfn id="vebt5"></dfn></td></mark></nobr><track id="vebt5"></track><dl id="vebt5"><code id="vebt5"><sup id="vebt5"><sub id="vebt5"></sub></sup></code></dl><del id="vebt5"></del><track id="vebt5"></track><video id="vebt5"></video><ol id="vebt5"></ol><track id="vebt5"></track><th id="vebt5"><menuitem id="vebt5"><wbr id="vebt5"><listing id="vebt5"></listing></wbr></menuitem></th><del id="vebt5"></del><sub id="vebt5"></sub><big id="vebt5"></big><b id="vebt5"></b><address id="vebt5"><progress id="vebt5"><noscript id="vebt5"></noscript></progress></address><del id="vebt5"><i id="vebt5"><optgroup id="vebt5"></optgroup></i></del><delect id="vebt5"></delect><dl id="vebt5"></dl><li id="vebt5"></li><tr id="vebt5"><option id="vebt5"><ol id="vebt5"><delect id="vebt5"></delect></ol></option></tr><th id="vebt5"><address id="vebt5"><wbr id="vebt5"><rt id="vebt5"></rt></wbr></address></th><strike id="vebt5"></strike><strike id="vebt5"></strike><noscript id="vebt5"></noscript><p id="vebt5"></p><dl id="vebt5"></dl><progress id="vebt5"><rt id="vebt5"><th id="vebt5"></th></rt></progress><tt id="vebt5"><object id="vebt5"><menu id="vebt5"><sub id="vebt5"></sub></menu></object></tt><menu id="vebt5"></menu><span id="vebt5"><noframes id="vebt5"><tr id="vebt5"></tr></noframes></span><form id="vebt5"></form><video id="vebt5"><span id="vebt5"><tt id="vebt5"></tt></span></video><b id="vebt5"></b><video id="vebt5"></video><center id="vebt5"><small id="vebt5"><noscript id="vebt5"><div id="vebt5"></div></noscript></small></center><cite id="vebt5"><xmp id="vebt5"><code id="vebt5"><small id="vebt5"></small></code></xmp></cite><pre id="vebt5"></pre><i id="vebt5"><ruby id="vebt5"><tt id="vebt5"></tt></ruby></i><font id="vebt5"><mark id="vebt5"><td id="vebt5"></td></mark></font></div> <a href="http://www.cabanatime.com/">_ŷպһ_վ߹ۿ_ŷһ߳</a> <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body> </html>