C++臨時物件(1)
C++ 是一門以效率見長的語言(雖然近來越來越多的人“不齒”談及效率,我深以為不然 ,在某一次的程式編寫中不對效率錙銖必較並不意味意味著我們就不應該追求更多的更好的做法)。總之吧,相比起其它語言,程式設計師們在使 C++ 的時候會更加有意識地去避免沒有效率的做法。在C++ 的程式中,臨時物件的產生就是損及效率的“惡因”之一,因此也產生出一些意思的技術和優化手段,這篇文章裡我總結一下最近在這些方面學習的一些收穫:
返回值優化(RVO)與具命返回值優化(NRVO)
這是一項編譯器做的優化,已經是一種很常見的優化手段了,放狗搜一下可以找到很多的資料,在 MSDN 裡也有相關的說明。
返回值優化,顧名思義,就是與返回值有關的優化(廢話……),是當函式是按值返回(而不是引用啊、指標啊)時,為了避免產生不必要的臨時物件以及值拷貝而進行的優化。
先看看下面的程式碼:
<span style="color: blue;"></span><span style="font-size: 18px;"> </span><div class="dp-highlighter bg_cpp" style="font-family: Consolas, "Courier New", Courier, mono, serif; font-size: 12px; width: 938.912px; overflow: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); margin: 18px 0px !important; background-color: rgb(231, 229, 220);"><div class="bar" style="padding-left: 45px;"><div class="tools" style="padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; border-left-width: 3px; border-left-style: solid; border-left-color: rgb(108, 226, 108); background-color: rgb(248, 248, 248);"><a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_plain.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">view plain</span></a><a target=_blank class="CopyToClipboard" title="copy to clipboard" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_copy.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">copy to clipboard</span></a><div style="position: absolute; left: 382px; top: 1040px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol class="dp-cpp" style="padding: 0px; border: none; color: rgb(92, 92, 92); margin: 0px 0px 1px 45px !important; background-color: rgb(255, 255, 255);"><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">typedef</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> unsigned </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">int</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">; </span></span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"></span><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">class</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> MyCla </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">{ </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"></span><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">public</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">: </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> MyCla(</span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> a_size = 10):size(a_size) { </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> p = </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">new</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">[size]; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> } </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> MyCla(MyCla </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">const</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> & a_right):size(a_right.size) { </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> p = </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">new</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">[size]; </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> memcpy(p, a_right.p, size*</span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">sizeof</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">(</span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">)); </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> } </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> MyCla </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">const</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">& operator = (MyCla </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">const</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> & a_right) { </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> size = a_right.size; </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> p = </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">new</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">[size]; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> memcpy(p, a_right.p, size*</span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">sizeof</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">(</span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">)); </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">return</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> *</span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">this</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> } </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> ~MyCla() { </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">delete</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> [] p; </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> } </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"></span><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">private</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;">: </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> *p; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">UINT32</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> size; </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">}; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">MyCla TestFun() { </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">return</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> MyCla(); </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">} </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"></span><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">int</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> _tmain(</span><span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); font-weight: bold; background-color: inherit;">int</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> argc, _TCHAR* argv[]) </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">{ </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> MyCla a = TestFun(); </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">return</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> 0; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">} </span></span></li></ol></div><textarea style="DISPLAY: none" class="cpp" rows="15" cols="50" name="code">typedef unsigned int UINT32; class MyCla { public: MyCla(UINT32 a_size = 10):size(a_size) { p = new UINT32[size]; } MyCla(MyCla const & a_right):size(a_right.size) { p = new UINT32[size]; memcpy(p, a_right.p, size*sizeof(UINT32)); } MyCla const& operator = (MyCla const & a_right) { size = a_right.size; p = new UINT32[size]; memcpy(p, a_right.p, size*sizeof(UINT32)); return *this; } ~MyCla() { delete [] p; } private: UINT32 *p; UINT32 size; }; MyCla TestFun() { return MyCla(); } int _tmain(int argc, _TCHAR* argv[]) { MyCla a = TestFun(); return 0; }</textarea><span style="font-size: 18px;"> </span>
TestFun() 函式返回了一個 MyCla 物件,而且是按值傳遞的。
在沒有任何“優化”之前,這段程式碼的行為也許 是這樣的:return MyCla() 這行程式碼中,構造了一個 MyCla 類的臨時的無名物件(姑且叫它t1),接著把 t1 拷貝到另一塊臨時物件 t2(不在棧上),然後函式儲存好 t2 的地址(放在 eax 暫存器中)後返回,TestFun 的棧區間被“撤消”(這時 t1 也就“沒有”了,t1 的生存域在 TestFun 中,所以被析構了),在 MyCla a = TestFun(); 這一句中,a 利用 t2 的地址,可以找到 t2 進行,接著進行構造。這樣 a 的構造過程就完成了。然後再把 t2 也“幹掉”。
可以看到,在這個過程中,t1 和 t2 這兩個臨時的物件的存在實在是很浪費的,佔用空間不說,關鍵是他們都只是為a的構造而存在,a構造完了之後生命也就終結了。既然這兩個臨時的物件對於程式設計師來說根本就“看不到、摸不著”(匿名物件嘛,你怎麼引用?),於是編譯器乾脆在裡面做點手腳,不生成它們!怎麼做呢?很簡單,編譯器“偷偷地”在我們寫的fun函式中增加一個引數 A&,然後把 a 的地址傳進去(注意,這個時候 a 的記憶體空間已經存在了,但物件還沒有被“構造”,也就是建構函式還沒有被呼叫),然後在函式體內部,直接用 a 來代替原來的“匿名物件”,在函式體內部就完成 a 的構造。這樣,就省下了兩個臨時變數的開銷。這就是所謂的“返回值優化”~!在 VC7 裡,按值返回匿名物件時,預設都是這麼做。
上面說的是“返回值優化(RVO)”,還有一種“具名返回值優化(NRVO)”,是對於按值返回“具名物件”(就是有名字的變數!)時的優化手段,其實道理是一樣的,但由於返回的值是具名變數,情況會複雜很多,所以,能執行優化的條件更苛刻,在下面三種情況下(來自 MSDN),NRVO 將一定不起作用:
- 不同的返回路徑上返回不同名的物件(比如if XXX 的時候返回x,else的時候返回y)
- 引入 EH 狀態的多個返回路徑(就算所有的路徑上返回的都是同一個具名物件)
- 在內聯asm語句中引用了返回的物件名。
不過就算 NRVO 不能進行,在上面的描述中的 t2 這個臨時變數也不會產生,對於 VC 的 C++ 編譯器來說,只要你寫的程式是把物件按值返回的,它會有兩種做法,來避免 t2 的產生。拿下面這個程式來說明:
<span style="color: rgb(1, 0, 1);"></span><div class="dp-highlighter bg_cpp" style="font-family: Consolas, "Courier New", Courier, mono, serif; font-size: 12px; width: 938.912px; overflow: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); margin: 18px 0px !important; background-color: rgb(231, 229, 220);"><div class="bar" style="padding-left: 45px;"><div class="tools" style="padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; border-left-width: 3px; border-left-style: solid; border-left-color: rgb(108, 226, 108); background-color: rgb(248, 248, 248);"><a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_plain.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">view plain</span></a><a target=_blank class="CopyToClipboard" title="copy to clipboard" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_copy.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">copy to clipboard</span></a><div style="position: absolute; left: 382px; top: 3810px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol class="dp-cpp" style="padding: 0px; border: none; color: rgb(92, 92, 92); margin: 0px 0px 1px 45px !important; background-color: rgb(255, 255, 255);"><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">MyCla TestFun2() { </span></span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> MyCla x(3); </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">return</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> x; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">} </span></span></li></ol></div><textarea style="DISPLAY: none" class="cpp" rows="15" cols="50" name="code">MyCla TestFun2() { MyCla x(3); return x; }</textarea><span style="font-size: 18px;"> </span>
一種做法是像 RVO一樣,把作為表示式中獲取返回值來進行構造的變數 a 當成一個引用引數傳入函式中,然後在返回語句之前,用要返回的那個變數來拷貝構造 a,然後再把這個變數析構,函式返回原呼叫點,a 就構造好了。
還有一種方式,是在函式返回的時候,不析構 x ,而直接把 x 的地址放到 exa 暫存器中,返回調到 TestFun2 的呼叫點上,這時,a 可以用 exa 中存著的地址來進行構造,a 構造完成之後,再析構原來的變數 x !是的,注意到其實這時,x 的生存域已經超出了 TestFun2,但由於這裡 x 所在 TestFun2 的棧雖然已經無效,但是並沒有誰去擦寫這塊存,所以 x 其實還是有效的,當然,一切都在彙編的層面,對於 C++ 語言層面來講是透明的。
嗯,(具名)返回值引用大約就是這麼多,在網上和 MSDN 上還能查到更多的例子和解釋,對於在多執行緒下 (N)RVO 需要注意什麼,嗯,我完全沒有多執行緒的經驗,不敢亂寫誤人子弟……
右值引用與 move 語意
“C++ 中臨時物件對效率產生的影響一直為人所詬病”(網上流傳的說法),NRVO 等手段也只有在一定程度上彌補這個不足(你知道,在很多情況下無法做優化)。在 C++98 確定後的十多年時間後,“Cpper神聖”們終於給出了另一個對付它的法寶——右值引用。
對於右值引用,目前我所見過的最好的講解是VC開發團隊blog中釋出的一篇長文(看這裡 ),在CPP blog上飄飄白雲的博主進行了全文翻譯 (譯得很棒),建議細讀三遍!理解裡面每一個例子~這樣至少你在右值引用的認識上就有了良好的基礎了。(嗯,我只讀了兩遍,下面說的東西有錯誤的話請原諒並指出 :) )
簡單的說,在C++中的左值,就是能取地址的表示式,比如var、++var之類的,右值就不是能取地址的表示式啦,比如常數 123、x++、x+y等等。
嗯,我們可以看到,右值常常就代表著臨時物件,也就常常意味著“被詬病的浪費……”
比如,z = x + y,這裡,翻譯得更“低層”一點,那麼這裡將是:
<span style="color: rgb(1, 0, 1);"></span><span style="font-size: 18px;"> <span style="color: rgb(1, 0, 1);"></span></span><div class="dp-highlighter bg_c-sharp" style="font-family: Consolas, "Courier New", Courier, mono, serif; font-size: 12px; width: 938.912px; overflow: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); margin: 18px 0px !important; background-color: rgb(231, 229, 220);"><div class="bar" style="padding-left: 45px;"><div class="tools" style="padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; border-left-width: 3px; border-left-style: solid; border-left-color: rgb(108, 226, 108); background-color: rgb(248, 248, 248);"><a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_plain.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">view plain</span></a><a target=_blank class="CopyToClipboard" title="copy to clipboard" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_copy.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">copy to clipboard</span></a><div style="position: absolute; left: 382px; top: 4846px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol class="dp-c" style="padding: 0px; border: none; color: rgb(92, 92, 92); margin: 0px 0px 1px 45px !important; background-color: rgb(255, 255, 255);"><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">temp = x + y </span></span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">z = temp </span></span></li></ol></div><textarea style="DISPLAY: none" class="c-sharp" rows="15" cols="50" name="code">temp = x + y z = temp</textarea><span style="font-size: 18px;"> </span>
這個temp是很尷尬的,不用它將無法實現正確、良好的 operator + 語意,用它就很難避免臨時物件產生的不良開銷。
我們回到上面 RVO 中的程式例子:
<span style="color: rgb(1, 0, 1);"></span><span style="font-size: 18px;"> </span><div class="dp-highlighter bg_c-sharp" style="font-family: Consolas, "Courier New", Courier, mono, serif; font-size: 12px; width: 938.912px; overflow: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); margin: 18px 0px !important; background-color: rgb(231, 229, 220);"><div class="bar" style="padding-left: 45px;"><div class="tools" style="padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; border-left-width: 3px; border-left-style: solid; border-left-color: rgb(108, 226, 108); background-color: rgb(248, 248, 248);"><a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_plain.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">view plain</span></a><a target=_blank class="CopyToClipboard" title="copy to clipboard" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_copy.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">copy to clipboard</span></a><div style="position: absolute; left: 382px; top: 5157px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol class="dp-c" style="padding: 0px; border: none; color: rgb(92, 92, 92); margin: 0px 0px 1px 45px !important; background-color: rgb(255, 255, 255);"><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">MyCla TestFun() { </span></span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; font-size: 18px; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> </span><span class="keyword" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 102, 153); font-weight: bold; background-color: inherit;">return</span><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"> MyCla(); </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">} </span></span></li></ol></div><textarea style="DISPLAY: none" class="c-sharp" rows="15" cols="50" name="code">MyCla TestFun() { return MyCla(); }</textarea><span style="font-size: 18px;"> </span>
看,這裡返回的 MyCla(),正是一個右值(我們就給它取個名吧,不然不好稱呼它,嗯,還叫 t1 吧)。在函式返回後,這個 t1 就被析構,它做的析構動作就是把原來申請的記憶體還給系統。想想在這之前,a 在幹什麼?a 在構造的時候向系統申請了一塊記憶體!一個申請,一個還回,一來一回多費事啊,如果能直接把 t1 擁有的記憶體給 a ,就不省事了嗎?反正 t1 馬上就要掛了。好,右值引用給了我們這種機會,我們為 MyCla 實現一個 move 語意的拷貝建構函式(不知道什麼是 move 拷貝構造?回頭看上面連結的文章三遍!):
<span style="color: rgb(1, 0, 1);"></span><span style="font-size: 18px;"> </span><div class="dp-highlighter bg_c-sharp" style="font-family: Consolas, "Courier New", Courier, mono, serif; font-size: 12px; width: 938.912px; overflow: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); margin: 18px 0px !important; background-color: rgb(231, 229, 220);"><div class="bar" style="padding-left: 45px;"><div class="tools" style="padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; border-left-width: 3px; border-left-style: solid; border-left-color: rgb(108, 226, 108); background-color: rgb(248, 248, 248);"><a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_plain.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">view plain</span></a><a target=_blank class="CopyToClipboard" title="copy to clipboard" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_copy.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">copy to clipboard</span></a><div style="position: absolute; left: 382px; top: 5624px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol class="dp-c" style="padding: 0px; border: none; color: rgb(92, 92, 92); margin: 0px 0px 1px 45px !important; background-color: rgb(255, 255, 255);"><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">MyCla(MyCla && a_right):size(a_right.size) { </span></span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> p = a_right.p; </span></span></li><li class="alt" style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; color: inherit; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important;"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;"> a_right.p = NULL; </span></span></li><li style="border-left-width: 3px; border-style: none none none solid; border-left-color: rgb(108, 226, 108); list-style: decimal-leading-zero outside; line-height: 18px; margin: 0px !important; padding: 0px 3px 0px 10px !important; background-color: rgb(248, 248, 248);"><span style="margin: 0px; padding: 0px; border: none; color: black; background-color: inherit;"><span style="margin: 0px; padding: 0px; border: none; font-size: 18px; background-color: inherit;">} </span></span></li></ol></div><textarea style="DISPLAY: none" class="c-sharp" rows="15" cols="50" name="code">MyCla(MyCla && a_right):size(a_right.size) { p = a_right.p; a_right.p = NULL; }</textarea><span style="font-size: 18px;"> </span>
當編譯器探知用於構造 a 的是一個右值時,就呼叫這個 move 建構函式,然後我們在這個函式裡偷樑換柱,把 t1 的資源竊取過來了。這樣,就算不使用 RVO,這個構造的開銷也是非常小的。
那麼,對於像:
<span style="color: rgb(1, 0, 1);"></span><div class="dp-highlighter bg_c-sharp" style="font-family: Consolas, "Courier New", Courier, mono, serif; font-size: 12px; width: 938.912px; overflow: hidden; padding-top: 1px; position: relative; border-color: rgb(204, 204, 204); margin: 18px 0px !important; background-color: rgb(231, 229, 220);"><div class="bar" style="padding-left: 45px;"><div class="tools" style="padding: 3px 8px 10px 10px; font-stretch: normal; font-size: 9px; line-height: normal; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; border-left-width: 3px; border-left-style: solid; border-left-color: rgb(108, 226, 108); background-color: rgb(248, 248, 248);"><a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/whf727/article/details/5980110#" style="text-decoration: none; border: none; padding: 1px; margin: 0px 10px 0px 0px; font-size: 9px; color: rgb(12, 137, 207); display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url("images/default/ico_plain.gif"); background-attachment: initial; background-color: inherit; background-size: initial; background-origin: initial; background-clip: initial; background-position: left top; background-repeat: no-repeat;"><span style="font-size: 18px;">view plain</span></a><a target=_b