理解C++ lvalue与rvalue
一個(gè)眾所周知的危險(xiǎn)錯(cuò)誤是,函數(shù)返回了一個(gè)局部變量的指針或引用。一旦函數(shù)棧被銷(xiāo)毀,這個(gè)指針就成為了野指針,導(dǎo)致未定義行為。而左值(lvalue)和右值(rvalue)的概念,本質(zhì)上,是理解“程序員可以放心使用的變量”。
?
空泛的討論先到這里,先看一段會(huì)報(bào)錯(cuò)的代碼:
#include <iostream>using std::cout; using std::endl;int foo(int &a) {return a; }int main() {int a = 1;cout << &a << endl;int *p = &foo(a); }這里,對(duì)foo(a)取地址會(huì)引起錯(cuò)誤: "lvalue required as left operand of assignment".字面理解是,&取地址運(yùn)算符只能獲取左值的地址。
毫無(wú)疑問(wèn)的是,foo(a)的值是存在的,是數(shù)值1。之所以報(bào)錯(cuò),是因?yàn)榫幾g器認(rèn)為它不是左值,不允許程序員獲取它存放的地址。
?
我對(duì)這點(diǎn)標(biāo)準(zhǔn)的理解是:
獲取一個(gè)臨時(shí)空間的地址通常意味著要對(duì)這塊內(nèi)存賦值。在C++程序中,臨時(shí)空間的銷(xiāo)毀時(shí)機(jī)是不確定(undefined)的,它隨時(shí)被用于其他臨時(shí)空間的存儲(chǔ)。于是程序員不允許使用這塊空間。聯(lián)系之前總結(jié)的堆棧概念,可以對(duì)C++中的變量存儲(chǔ)有更深的理解。
https://www.cnblogs.com/kinsang/p/6855579.html
?
在堆棧概念一文,我小結(jié)了C++程序中數(shù)據(jù)可以存在三個(gè)地方:
1. 函數(shù)棧,在函數(shù)體內(nèi)的定義的變量
2. 堆,特別指使用new,malloc獲取的內(nèi)存空間
3. 靜態(tài)數(shù)據(jù)區(qū),即.data 和.bss
?
對(duì)于lvalue的通俗描述,是“具有確定地址的非臨時(shí)對(duì)象”,而不滿足lvalue定義的值均被認(rèn)為是rvalue。換句話說(shuō),C++程序里面出現(xiàn)的值,非左即右。下面我們分析一下這三個(gè)存放數(shù)據(jù)的區(qū)域里面可以被使用的值的情況:
堆
堆的空間上的變量完全由程序員申請(qǐng)和管理的,所以它們都有明確的地址,是可以放心使用的左值。
靜態(tài)數(shù)據(jù)區(qū)
對(duì)于靜態(tài)數(shù)據(jù)區(qū),盡管存放的位置是固定的,但里面的數(shù)據(jù)并不能認(rèn)為都是左值。主要是因?yàn)槔锩嬗小白置嬷怠?#xff0c;包括const所實(shí)現(xiàn)的常量,即靜態(tài)存儲(chǔ)而不能被修改的值。
函數(shù)棧
當(dāng)函數(shù)調(diào)用發(fā)生的時(shí)候,系統(tǒng)會(huì)創(chuàng)建函數(shù)棧,保留上下文,函數(shù)調(diào)用結(jié)束的時(shí)候,函數(shù)棧內(nèi)的變量會(huì)被銷(xiāo)毀。函數(shù)體里面定義的變量是左值,而臨時(shí)變量是右值。
?
拓展
C++ 11標(biāo)準(zhǔn),為了更好地利用臨時(shí)變量,提出Rvalue Reference,對(duì)應(yīng)的的實(shí)現(xiàn)是move semantics (轉(zhuǎn)移語(yǔ)意)和Perfect Forwarding(完美轉(zhuǎn)發(fā))。對(duì)這些新特性還不了解,暫時(shí)不寫(xiě)。
?
參考:
http://www.cnblogs.com/dejavu/archive/2012/09/02/2667640.html
http://stackoverflow.com/questions/230584/where-are-variables-in-c-stored
http://eli.thegreenplace.net/2011/12/15/understanding-lvalues-and-rvalues-in-c-and-c
lvalue和rvalue
在計(jì)算機(jī)的遠(yuǎn)古時(shí)代,變量的lvalue和rvalue是指:
lvalue:變量在內(nèi)存中的位置。通過(guò)它能夠找到內(nèi)存中存放的變量(location value);
rvalue:存放在lvalue對(duì)應(yīng)的內(nèi)存中的東西(register value);
C++中的每個(gè)表達(dá)式要么是lvalue要么是rvalue。lvalue表示一個(gè)內(nèi)存位置,而rvalue表示計(jì)算表達(dá)式的結(jié)果。
rvalue引用是對(duì)有名稱變量的引用,并允許變量表示的內(nèi)存通過(guò)lvalue引用來(lái)訪問(wèn)。
rvalue引用是對(duì)包含表達(dá)式結(jié)果的內(nèi)存位置的引用。
lvalue引用:
使用lvalue引用形參,可以編寫(xiě)直接訪問(wèn)調(diào)用者實(shí)參的函數(shù),避免了按值傳遞中的隱式復(fù)制。若不修改實(shí)參,只需要給lvalue引用類(lèi)型使用const修飾符,以避免意外修改參數(shù)。無(wú)論是按值傳遞、按址傳遞參數(shù)或引用都是編譯器的規(guī)則,我們需要熟悉參數(shù)在不同情況下的傳遞,好的理解方式就是輸出地址來(lái)觀察。
lvalue引用:
使用lvalue引用形參,可以編寫(xiě)直接訪問(wèn)調(diào)用者實(shí)參的函數(shù),避免了按值傳遞中的隱式復(fù)制。若不修改實(shí)參,只需要給lvalue引用類(lèi)型使用const修飾符,以避免意外修改參數(shù)。無(wú)論是按值傳遞、按址傳遞參數(shù)或引用都是編譯器的規(guī)則,我們需要熟悉參數(shù)在不同情況下的傳遞,好的理解方式就是輸出地址來(lái)觀察。
?
?
[cpp]?view plain?copy輸出結(jié)果:v=7.
rvalue引用:
首先,舉一個(gè)報(bào)錯(cuò)的例子: [cpp]?view plain?copy參考:
?
?
http://blog.chinaunix.net/uid-7471615-id-83794.html
http://blog.csdn.net/rogerhe/article/details/6410993?
http://www.cnblogs.com/yunqie/p/5892252.html?
轉(zhuǎn)載于:https://www.cnblogs.com/pityhero233/p/8601319.html
總結(jié)
以上是生活随笔為你收集整理的理解C++ lvalue与rvalue的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: The application serv
- 下一篇: ffmpeg使用总结