Re: [翻譯] Rvalue References: C++0x Features in …

看板C_and_CPP (C/C++)作者時間14年前 (2010/09/08 00:06), 編輯推噓3(300)
留言3則, 3人參與, 最新討論串3/3 (看更多)
啊...最近在跟人討論rvalue reference的問題 熊熊想到板上有這篇文章 就來做一下update Stephan Lavavej有說過 他有打算要寫rrv2 (rvalue reference v2) 更改的地方 不過到目前為止他沒空動手XD 其實我也沒空(逃) 所以就簡略的更新一下.. 總之最重要的一點就是原文最後面那段 the future N2812「A safety Problem With Rvalue Reference (and what to do about it)」提出 了一個初始化規則的變動,可以防止 rvalue reference 被繫結到 lvalue 上面。裡面提 到這項改變並不會影響 move 語意跟完美轉發,所以你現在學到的東西都還是有用(但 std::move() 跟 std::forward() 的實做會改變)。 N2812「A safety Problem With Rvalue Reference (and what to do about it)」 這個造成了之後的規則變更 N2844「Fixing a Safety Problem with Rvalue References」 http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2009/n2844.html 所以你現在不能把一個lvalue bind到rvalue reference上了 詳細的原因自己看連結(逃) ※ 引述《yoco315 (眠月)》之銘言: : 這篇文章的原始出處是 Visual C++ Team Blog 的 Rvalue References: C++0x : Features in VC10, Part 2,作者是 Stephan T. Lavavej。 : (原始網址:http://tinyurl.com/d7k8xk) : 這篇文章是獲得原作者 Stephan 的許可之後進行中文翻譯的, : (我自己習慣把 Type& 唸作「Type ref」,Type&& 唸作「Type ref ref」。這樣就是 : Type 的 lvalue reference 跟 Type 的 rvalue reference。就像是一個常數指標指到 : 一個 int,我們寫作「int * const」,也可以唸成「int star const」。) : 那他們之間到底差在哪裡?Rvalue reference 在初始化以及多載函數決議的時候跟 : lvalue reference 有不同的行為。這兩者對於初始化的時候,繫結的對象以及多載決議 : 的時候有不同的偏好。 : 1. Type&,我們已經知道 Type& 只能繫結到 non-const lvalue,其他的一概不能。 : 2. const Type&,我們也知道 const Type& 可以繫結到所有的東西。 : 3. Type&& 可以繫結到 non-const lvalue 還有 non-const rvalue,但是不能繫結到 : const lvalue 跟 const rvalue,因為那樣會違反常數性) : 4. const Type&& 可以繫結到所有的東西。 嗯 所以這段要改寫 1.和2.是沒變的 3. 現在Type&&只能繫結到non-const rvalue 4. const Type&&還是能bind到任何東西 道理和2.一樣 : 把一個 non-const rvalue 繫結到一個 const rvalue 是沒問題的。因為 non-const ^^^^^ 這裡有一個typo..原文寫的是non-const : rvalue 的重點就是可以用來修改暫時變數。 (中間這一大段沒什麼變) : 如果你真的很想用你的 move 指派運算子來實做你的 move 建構子,你需要一項特異功能 : :把一個 lvalue 看作是一個 rvalue。C++0x 的 <utility> 裡面的 std::move() 提供 : 你這個能力。VC10 將會有這個功能(其實我自己現在用的開發版已經有了),但是不好 : 意思現在還是 VC10 CTP,沒有。所以我會教你怎麼重頭打造一個 move()。 : C:\Temp>type unified_right.cpp : #include <stddef.h> : #include <iostream> : #include <ostream> : using namespace std; : template <typename T> struct RemoveReference { : typedef T type; : }; : template <typename T> struct RemoveReference<T&> { : typedef T type; : }; : template <typename T> struct RemoveReference<T&&> { : typedef T type; : }; : template <typename T> typename RemoveReference<T>::type&& Move(T&& t) { : return t; : } 這裡是一個問題點 我們知道T&& t是一個具名的Rvalue reference 所以它是一個lvalue 而Move()函數的return type是一個 rvalue reference return t; 這一行事實上把一個rvalue reference bind到 lvalue上 我們之前說過,現在你不能這樣幹了 所以這行要改寫成.. return static_cast< typename RemoveReference<T>::type&& >(t); 也就是說你必須強制轉型才能傳回正確的T&& 同理std::forword()的實作也要作類似的改變 現在也許你會有個問題: 既然我們可以用static_cast<>把lvalue bind到Rvalue reference 那為什麼我們還需要std::move()? 沒錯,對於一個MyType&& t; 事實上你寫.. std::move(t); 或是 static_cast<MyType&&>(t); 得到的是完全一樣的結果 std::move()的實作只是用模板幫你推導出MyType&& 當然,因為static_cast少用為妙 所以建議還是使用std::move()來取得rvalue reference -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.136.182.215

09/08 00:18, , 1F
rvalur ref真是偉大的進步...XD
09/08 00:18, 1F

09/08 00:28, , 2F
至少背的時候比較容易... (  ̄ c ̄)y▂ξ
09/08 00:28, 2F

09/08 01:05, , 3F
推薦這篇文章
09/08 01:05, 3F
文章代碼(AID): #1CXcCKDZ (C_and_CPP)
文章代碼(AID): #1CXcCKDZ (C_and_CPP)