左值 右值與應用

2021-10-04 06:33:34 字數 1850 閱讀 6156

關於什麼是左值、什麼是右值,可以參考官方定義

還有一篇文章

下面將對左值和右值的用法進行剖析,反向理解什麼是左值、右值。

右值據有兩個特點:

所引用的物件將要被銷毀

該物件沒有其他使用者

使用右值引用**可以自由地接管所引用的物件的資源

程式的資料一般放在記憶體,那麼需要用到的時候,直接取用。例如

int a = 10;
當我們需要使用a這個名字所代表的記憶體值,通過a就可以找到這塊記憶體。並且可以做如下操作

a = a + 1
在上面的式子中,將a的值取出到暫存器與1相加,再把相加後的值放回a中。同時,上式中a是左值,a+1是右值,可以看出,a+1的過程是在暫存器中進行的,結果也放在暫存器中。然後再把結果放回a指向的記憶體。下一刻,該暫存器的a+1可能又被什麼運算的結果覆蓋掉了。

這就是primer 5th所說的所引用的物件將要被銷毀(p471)。

為了不浪費這個值(a+1),c++編譯器通過右值引用的方式延長a+1(這個值在暫存器中)。例如

int &&r = a + 1;

int v = r;

int &&r2 = std::move(r);

r是a+1的右值引用,同時r是左值。

基本資料型別有左右值之分,類也有左右值。即如果可以使用右值引用繫結基本型別,那麼也可以繫結類。對於類而言,存在移動建構函式和移動賦值函式。

什麼時候呼叫移動操作,類似上面的第二個賦值操作,此時就會呼叫移動操作,竊取暫存器資源。所以需要實現類的移動建構函式和移動賦值函式。

右值應用最強大的地方是在類能夠輕易使用右值,減少拷貝的開銷

下面是移動建構函式(primer 5th p473)

strvec::strvec(strvec &&s) noexcept

: elements(s.elements), first_free(s.first_free), cap(s.cap)

下面**是沒有意義的,只是為了說明

strvec sv1;                  //(1)

strvec sv2 = sv1; //(2)

strvec sv3 = std::move(sv1); //(3)

這裡涉及到&&s這個變數,如果用乙個右值去呼叫strvec建構函式(3),不會重新分配任何記憶體,而是直接接管s的記憶體。最終s(移源後的物件 sv1)被銷毀了,則呼叫析構函式,而析構函式析構的elements/first_free/cap都被置為nullptr,不會影響sv3。

但是這裡需要注意,因為sv1使用了move,將sv1左值轉換為右值使用,除了對sv1賦值和銷毀(離開作用域),不能使用sv1的值。即可以賦予它新值,但是不能使用移源後物件的值。

strvec &strvec::operator=(strvec &&rhs) noexcept

return *this;

}

移動構造和移動賦值都是將移源後的物件置於與預設初始化的物件相同的狀態。

沒有移動操作,對於右值物件的拷貝和賦值操作,都會呼叫最普通的拷貝構造和賦值操作。有了移動操作,主要有哪些應用場景呢?

1、函式返回的是乙個右值,就可以呼叫移動操作

class hasptr 

hasptr& operator=(hasptr rhs)

}

在類**小心使用move,可以大幅度提公升效能。但是乙個移源後物件具有不確定的狀態,對其呼叫std::move是危險的。呼叫move時,必須絕對確認移源後物件沒有其他使用者

左值與右值

本文摘自 http jiang5005.spaces.live.com blog cns 619f3de8ab99988e 111.entry?action post wa wsignin1.0 8月20日 c 中的左值和右值 1.概念 變數和文字常量都有儲存區,並且有相關的型別,區別在於變數是可定...

左值與右值

左值就是那些能夠出現在賦值符號左邊的東西。右值就是那些可以出現賦值符號右邊的東西。例如 a b 25 a就是乙個左值,因為它標識了乙個可以儲存結果值的地點,b 25是個右值,因為它指定了乙個值。但是它們可以互換嗎?b 25 a 原先用作左值的a此時也可以當作右值,因為每個位置都 包含乙個值。然而,b...

左值與右值

對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物件,右值是指表示式結束時就不再存在的臨時物件。乙個區分左值與右值的便捷方法是 看能不能對表示式取位址,如果能,則為左值,否則為右值。下面給出一些例子來進行說明...