<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 右值引用 左值(賦值操作符“=”的左側,通常是一個變量)與右值(賦值操作符“=”的右側,通常是一個常數、表達式、函數調用)之間的差別可以追溯到 Christopher Strachey (C++的祖先語言CPL之父,指稱語義學之父)時代。在C++中,左值可被綁定到非const引用,左值或者右值則可被綁定到const引用。但是卻沒有什么可以綁定到非const的右值(譯注:即右值無法被非const的引用綁定),這是為了防止人們修改臨時變量的值,這些臨時變量在被賦予新的值之前,都會被銷毀。例如: ``` void incr(int& a) { ++a; } int i = 0; incr(i); // i變為1 //錯誤:0不是一個左值 incr(0); //(譯注:0不是左值,無法直接綁定到非const引用:int&。 // 假如可行,那么在調用時,將會產生一個值為0的臨時變量, // 用于綁定到int&中,但這個臨時變量將在函數返回時被銷毀, // 因而,對于它的任何更改都是沒有意義的, // 所以編譯器拒絕將臨時變量綁定到非const引用,但對于const的引用, // 則是可行的) ``` 假設incr(0)合法,那么要么產生一個程序員不可見的臨時變量并進行無意義的遞增操作,要么發生更悲劇的情況:把字面常量“0”的實際值會變成1。盡管后者聽起來是天方夜譚,但是對于早期Frotran等這一類把字面常量“0”也存到內存里的某個位置的編譯器來說,這真的會變成一個bug。(譯注:指的是假如把用于存儲字面常量0的內存單元上的值從0修改為1以后,后續所有使用字面常數0的地方實際上都在使用“1”)。 到目前為止,一切都很美好。但考慮如下函數: ``` template<class T> swap(T& a, T& b) // 老式的swap函數 { T tmp(a);// 現在有兩份"a" a = b; // 現在有兩份"b" b = tmp; // 現在有兩份tmp(值同a) } ``` 如果T是一個拷貝代價相當高昂的類型,例如string和vector,那么上述swap()操作也將煞費氣力(不過對于標準庫來說,我們已經針對string和vector的swap()進行了特化來處理這個問題)。注意這個奇怪的現象,我們的初衷其實并不是為了把這些變量拷來拷去,我是僅僅是想將變量a,b,tmp的值做一個“移動”(譯注:即通過tmp來交換a,b的值)。 在C++11中,我們可以定義“移動構造函數(move constructors)”和“移動賦值操作符(move assignments”來“移動”而非復制它們的參數: ``` template<class T> class vector { // … vector(const vector&); // 拷貝構造函數 vector(vector&&); // 移動構造函數 vector& operator= (const vector&); // 拷貝賦值函數 vector& operator =(vector&&); // 移動賦值函數 }; //注意:移動構造函數和移動賦值操作符接受 // 非const的右值引用參數,而且通常會對傳入的右值引用參數作修改 ``` ”&&”表示“右值引用”。右值引用可以綁定到右值(但不能綁定到左值): ``` X a; X f(); X& r1 = a; // 將r1綁定到a(一個左值) X& r2 = f(); // 錯誤:f()的返回值是右值,無法綁定 X&& rr1 = f(); // OK:將rr1綁定到臨時變量 X&& rr2 = a; // 錯誤:不能將右值引用rr2綁定到左值a ``` 移動賦值操作背后的思想是,“賦值”不一定要通過“拷貝”來做,還可以通過把源對象簡單地“偷換”給目標對象來實現。例如對于表達式s1=s2,我們可以不從s2逐字拷貝,而是直接讓s1“侵占”s2內部的數據存儲(譯注:比如char* p),并以某種方式“刪除”s1中原有的數據存儲(或者干脆把它扔給s2,因為大多情況下s2隨后就會被析構)。(譯注:仔細體會copy與move的區別。) 我們如何知道源對象能否“移動”呢?我們可以這樣告訴編譯器:(譯注:通過move()操作符) ``` template <class T> void swap(T& a, T& b) //“完美swap”(大多數情況下) { T tmp = move(a); // 變量a現在失效(譯注:內部數據被move到tmp中了) a = move(b); // 變量b現在失效(譯注:內部數據被move到a中了,變量a現在“滿血復活”了) b = move(tmp); // 變量tmp現在失效(譯注:內部數據被move到b中了,變量b現在“滿血復活”了) } ``` move(x) 意味著“你可以把x當做一個右值”,把move()改名為rval()或許會更好,但是事到如今,move()已經使用很多年了。在C++11中,move()模板函數(參考“brief introduction”),以及右值引用被正式引入。 右值引用同時也可以用作完美轉發(perfect forwarding)。(譯注:比如某個接口函數什么也不做,只是將工作“委派”給其他工作函數) 在C++11的標準庫中,所有的容器都提供了移動構造函數和移動賦值操作符,那些插入新元素的操作,如insert()和push_back(), 也都有了可以接受右值引用的版本。最終的結果是,在沒有用戶干預的情況下,標準容器和算法的性能都提升了,而這些都應歸功于拷貝操作的減少。 參考: * the C++ draft section ??? * N1385 N1690 N1770 N1855 N1952 * [N2027==06-0097] Howard Hinnant, Bjarne Stroustrup, and Bronek Kozicki: [A brief introduction to rvalue references](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html) * [N1377=02-0035] Howard E. Hinnant, Peter Dimov, and Dave Abrahams: [A Proposal to Add Move Semantics Support to the C++ Language](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm) (original proposal). * [N2118=06-0188] Howard Hinnant: [A Proposal to Add an Rvalue Reference to the C++ Language Proposed Wording (Revision 3)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html) (final proposal). (翻譯:dabaitu,感謝:dave)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看