• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            CG@CPPBLOG

            /*=========================================*/
            隨筆 - 76, 文章 - 39, 評(píng)論 - 137, 引用 - 0
            數(shù)據(jù)加載中……

            數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換

            1、左值和右值

            表達(dá)式的左值是它的地址,右值是該地址所存儲(chǔ)的內(nèi)容。比如下面代碼:

            = x + 1;

            這兩個(gè) x 有什么不同呢?第一個(gè)表達(dá)式 x 表示的是它的左值,而第二個(gè)表達(dá)式 x 表示的是它的右值。一個(gè)表達(dá)式能不能放到 賦值操作符 的左邊,取決于這個(gè)表達(dá)式有沒(méi)有左值,同樣的,一個(gè)表達(dá)式能不能放到 賦值操作符 的右邊,取決于它有沒(méi)有右值。

            一個(gè)表達(dá)式究竟是取左值還是右值,需要結(jié)合上下文,大多數(shù)表達(dá)式同時(shí)具有左值和右值。

            2、指針類型、數(shù)組類型和函數(shù)類型

            C++是一種強(qiáng)類型語(yǔ)言,類型在程序中的非常重要,每個(gè)變量和表達(dá)式都有一個(gè)確定的類型,類型匹配和類型轉(zhuǎn)換也是C++語(yǔ)言中的重要部分。除了內(nèi)建的一些類型和用戶自定義類型(包括類類型),下面重點(diǎn)說(shuō)一下指針類型、數(shù)組類型和函數(shù)類型。

            T* a; 

            聲明一個(gè)變量a,它的類型是T*(指向類型T的指針類型)。

            T arr[100];

            聲明一個(gè)變量arr,它的類型是 T[100](一維,維長(zhǎng)100,元素類型為T的數(shù)組)。

            T f(void){/*  . . . */}

            聲明一個(gè)變量f,它的類型是 T(void)(返回值為T,參數(shù)為void的函數(shù))

            特別要強(qiáng)調(diào)的是,arr 的類型和 f 的類型都不是指針。這兩個(gè)類型的表達(dá)式?jīng)]有右值。

            3、&、* 操作符

            * 操作符應(yīng)用與左值表達(dá)式,以表達(dá)式左值為地址,取出表達(dá)式類型的值,作為右值返回。
            & 操作符應(yīng)用于左值表達(dá)式,返回表達(dá)式的左值。

            注意*、& 操作符的操作數(shù)必須擁有左值。

            4、左值到右值的轉(zhuǎn)換

            C++ 標(biāo)準(zhǔn)轉(zhuǎn)換包含 左值到右值的轉(zhuǎn)換。因?yàn)閿?shù)組類型和函數(shù)類型的表達(dá)式?jīng)]有右值,所以特別這里要說(shuō)明數(shù)組類型和函數(shù)類型到右值的轉(zhuǎn)換。比如上文所說(shuō) arr ,當(dāng)它作為賦值操作符的操作數(shù)時(shí),它需要轉(zhuǎn)換為 T* 類型的指針(注意類型是指針!!),其值等于第一個(gè)元素的地址。而上文中所說(shuō)的 f,當(dāng)它作為賦值操作符的操作數(shù)時(shí),它需要轉(zhuǎn)換為 T(*)(void) 的指針(注意類型是指針!!),它指向f的地址。

            5、對(duì)數(shù)組類型或者函數(shù)類型施加&、*操作符

            &arr、 *arr、 &f、 *f 這些表達(dá)式都是什么呢?打開RTTI,在VC里運(yùn)行下面代碼:

             1 #include "stdafx.h"
             2 #include <iostream>
             3 using namespace std;
             4 
             5 int func()
             6 {
             7         int i = 2;
             8         return i;
             9 }
            10 
            11 int _tmain(int argc, _TCHAR* argv[])
            12 {
            13         int arr[100= {0,1,2,3};
            14 
            15         cout<<typeid(func).name()<<endl;
            16         cout<<typeid(*func).name()<<endl;
            17         cout<<typeid(&func).name()<<endl;
            18         cout<<endl;
            19         cout<<typeid(arr).name()<<endl;
            20         cout<<typeid(*arr).name()<<endl;
            21         cout<<typeid(&arr).name()<<endl;
            22         cout<<typeid(int*).name()<<endl;        
            23 
            24         getchar();
            25         return 0;
            26 }

            運(yùn)行結(jié)果如下:

            int __cdecl(void)
            int __cdecl(void)
            int (__cdecl*)(void)

            int 
            [100]
            int
            int (*)
            [100]
            int *

            可以看出 *func 和 func 類型相同,是函數(shù)類型,而&func 是指向函數(shù)的指針。arr 是數(shù)組類型,*arr 是 T 類型, &arr 是 指向數(shù)組的指針(這個(gè)比較費(fèi)解)

            因?yàn)?func 和 func 是等價(jià)的,所以可以這樣調(diào)用 func:

            (***********************func)();

            如果要用 &func,必須這樣(注意第一個(gè)一定是 *):

            (*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&func)();

            至于 arr、*arr、&arr 因?yàn)轭愋筒煌豢苫煊茫?dāng)然用來(lái) memset 的話,表達(dá)式 arr 和 &arr 的值都為第一個(gè)元素的地址,最終都被轉(zhuǎn)換為 void* 。




            posted on 2008-04-07 22:50 cuigang 閱讀(4460) 評(píng)論(28)  編輯 收藏 引用 所屬分類: C/C++

            評(píng)論

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            幾個(gè)錯(cuò)誤:
            左值:返回一個(gè)可修改對(duì)象的表達(dá)式稱為左值
            右值:返回一個(gè)不可修改對(duì)象的表達(dá)式稱為右值
            *操作符返回的對(duì)象可能是左值也可能是右值
            &操作符可用于左值和右值
            *操作符的操作數(shù)可以是右值(請(qǐng)參考“映射設(shè)備寄存器到內(nèi)存”http://blog.chinaunix.net/u/12783/showart_385250.html
            arr是T [100],那么&arr就是T (*)[100],沒(méi)什么費(fèi)解的
            2008-04-08 10:27 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            給樓上的糾兩個(gè)錯(cuò):

            “左值:返回一個(gè)可修改對(duì)象的表達(dá)式稱為左值”

            左值未必都是可修改的,例如數(shù)組名就是不可修改的左值,可參見Expert C Programming 4.3.1

            “右值:返回一個(gè)不可修改對(duì)象的表達(dá)式稱為右值”

            右值未必都是不可修改的;在C++中,built-in的右值總是不可修改的,但是對(duì)于user defined type 的右值,在某些情況下是允許被修改;例如對(duì)于函數(shù)返回的臨時(shí)對(duì)象,調(diào)用non-const member function是合法的

            2008-04-08 18:09 | 嘯天豬

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @raof01

            1、我并非說(shuō)我的左值右值描述是定義,但是你的依靠是否可修改的判斷卻反而是錯(cuò)的,一個(gè)const變量x,表達(dá)式 x 仍然有右值,但是不代表 x 可修改。關(guān)于左值和右值,ISO C++ 98版標(biāo)準(zhǔn)這樣說(shuō):

            An lvalue for an object is necessary in order to modify the object except that an rvalue of class type can also be used to modify its referent under certain circumstances.

            而《C++ primer》4th 這樣說(shuō):

            存儲(chǔ)數(shù)據(jù)值的那塊內(nèi)存的地址,它有時(shí)被稱為變量的左值lvalue,讀作ell-value,我們也可認(rèn)為左值的意思是位置值(location value)。

            左值代表了一個(gè)可被程序?qū)ぶ返膶?duì)象,可以從該對(duì)象讀取一個(gè)值,除非該對(duì)象被聲明為const,否則它的值也可以被修改。相對(duì)來(lái)說(shuō),右值只是一個(gè)表達(dá)式,它表示了一個(gè)值,或一個(gè)引用了臨時(shí)對(duì)象的表達(dá)式,用戶不能尋址該對(duì)象,也不能改變它的值。

            2、我承認(rèn)對(duì)于 * 操作符用于左值的描述有問(wèn)題,應(yīng)該說(shuō) 解引用操作符 用于指針類型,但 & 操作符的確只能應(yīng)用于有左值的表達(dá)式,看C++ 標(biāo)準(zhǔn)這樣說(shuō):

            The result of the unary & operator is a pointer to its operand. The operand shall be and lvalue or a qualified-id.

            The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.

            至于你鏈接的文章,請(qǐng)恕我未能洞悉,不知里面哪里提到 解引用操作符可以用于右值,或者隱含此意味。

            雖然標(biāo)準(zhǔn)中沒(méi)有說(shuō) 解引用操作符 到底是用在左值還是右值表達(dá)式上,但是間接尋址(indirection)反而說(shuō)明了你的觀點(diǎn),它是將指針變量的右值作為地址來(lái)訪問(wèn)指向物,類似的有
            ‘.’,‘->’運(yùn)算符。

            3、我說(shuō)指向數(shù)組的指針費(fèi)解,不是說(shuō)我不理解,只是說(shuō)大多數(shù)人實(shí)際中難以見到,不好理解,如果你可以理解,你可以說(shuō)說(shuō)它和多維數(shù)組 arr[][] 的 指針 arr[2] 有什么區(qū)別。

            2008-04-08 21:44 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            哪個(gè)是對(duì)的,不要誤解人
            2008-04-09 16:14 | 我愛(ài)你

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @cuigang
            想太多反而會(huì)把問(wèn)題搞復(fù)雜。

            C++ Primer 4th: ch2.3.1
            左值可以出現(xiàn)在賦值語(yǔ)句(等號(hào))的左邊或右邊。
            右值只能出現(xiàn)在賦值(等號(hào))的右邊,不能出現(xiàn)在賦值語(yǔ)句的左邊。

            無(wú)論在哪本C/C++書籍中,對(duì)左值、右值的描述最基本的就是以上兩句話。其他關(guān)于左值、右值話題的討論、延伸都脫離不了以上兩句話。

            至于左值是否是地址,右值是否為數(shù)據(jù)本身——
            對(duì)于 x = x + 1;
            假設(shè) x 為 int 類型,則編譯后匯編語(yǔ)句應(yīng)該為:
            mov eax, DWORD PTR x_$[ebp]
            inc eax
            mov DWORD PTR x_$[ebp], eax

            很明顯 ebp 是地址而不是具體數(shù)據(jù),而右邊的 x 是作為右值出現(xiàn)的。也就是說(shuō)除非字面值表達(dá)式(1, 'a'等),其他表達(dá)式不管左值右值,編譯器都有可能以地址處理。

            至于右值是否能被尋址——
            const int iX = 100;
            cout << &iX << endl;
            是合法的。從加上const關(guān)鍵字那一刻起,iX就只能作為右值出現(xiàn)。
            試圖用強(qiáng)悍的指針來(lái)修改iX的值:
            int* pX = &iX; //無(wú)法從“const int *”轉(zhuǎn)換為“int *”
            *pX = 101;

            不是糾錯(cuò),只是討論。
            2008-04-09 23:20 | ww

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @嘯天豬
            看起來(lái)比較抽象,能詳細(xì)舉例說(shuō)明嗎?
            2008-04-09 23:22 | iwong

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            我覺(jué)得不嚴(yán)謹(jǐn)?shù)睦斫猓笾稻褪浅绦騿T有權(quán)知道其地址的object;右值則是雖然知道這個(gè)object的存在,但是它的地址對(duì)程序員是無(wú)意義的。

            至于左值/右值的準(zhǔn)確含義,還是參考標(biāo)準(zhǔn)吧;書畢竟是面向大眾的,通常不會(huì)像標(biāo)準(zhǔn)那樣給出完整、嚴(yán)謹(jǐn)、天書般的定義

            @iwong

            建議參考水木社區(qū)Cplusplus版的FAQ,解釋的很詳細(xì)

            http://www.newsmth.net/bbscon.php?bid=335&id=179727

            2008-04-10 00:38 | 嘯天豬

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @嘯天豬

            你提供的鏈接解釋很充分,希望你自己也能自己看一下
            2008-04-10 22:08 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @ww

            嘯天豬的鏈接你看一下,&只能對(duì)左值表達(dá)式取址。我就不用再?gòu)U話了。
            2008-04-10 22:20 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            向前輩致敬~
            2008-04-11 22:58 | elent

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @嘯天豬
            @cuigang

            http://www.newsmth.net/bbscon.php?bid=335&id=179727
            這篇文章把能夠用&x取得地址的x都視為左值,于是"Hello world!"這樣的字面值字符串和const常量都成為了左值。

            可是:
            const int i = 1;
            i++;
            "Hello world!"++;

            在VC中編譯時(shí)對(duì)后兩行都會(huì)提示“++需要左值”。

            如果相信這篇文章的話,那么這個(gè)結(jié)果是很令人費(fèi)解的。
            2008-04-12 14:30 | iwong

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @iwong

            你需要區(qū)分概念:左值分為兩類──可修改的左值和不可修改的左值。通常提到的左值都指的是前者──例如上面VC的提示



            3.10 Lvalues and rvalues [basic.lval]

            Every expression is either an lvalue or an rvalue.

            If an expression can be used to modify the object to which it refers, the expression is called modifiable. A
            program that attempts to modify an object through a nonmodifiable lvalue or rvalue expression is ill-formed.


            我自己的理解:

            rvalue意味著object的地址對(duì)程序員無(wú)意義──它的地址對(duì)編譯器有用,對(duì)程序員是沒(méi)用的

            modifibale lvalue 意味著object的地址對(duì)程序員有意義,且可以用這個(gè)lvalue對(duì)object進(jìn)行修改

            unmodifiable lvalue意味著object的地址對(duì)程序員有意義,但若通過(guò)這個(gè)lvalue對(duì)object進(jìn)行修改,也是無(wú)意義的(編譯報(bào)錯(cuò)或者運(yùn)行出錯(cuò))

            i++出錯(cuò)的原因在于”const int i=1“中的i并不是可修改的左值

            而標(biāo)準(zhǔn)規(guī)定,前綴/后綴增量的操作對(duì)象必須是modifiable lvalue

            ”5.2.6 Increment and decrement [expr.post.incr]
            1 The value obtained by applying a postfix ++ is the value that the operand had before applying the operator.The operand shall be a modifiable lvalue.

            5.3.2 Increment and decrement [expr.pre.incr]
            1 The operand of prefix ++ is modified by adding 1, or set to true if it is bool (this use is deprecated). The operand shall be a modifiable lvalue. “


            ”Hello world!“++出錯(cuò)的原因在于這里發(fā)生了string literal 到 pointer的自動(dòng)轉(zhuǎn)換,”hello wolrd“轉(zhuǎn)換為類型為char *的rvalue。對(duì)于一個(gè)built-in type的rvalue執(zhí)行增量操作,肯定是不合法的


            4.2 Array-to-pointer conversion

            2 A string literal (2.13.4) that is not a wide string literal can be converted to an rvalue of type “pointer to char”;
            2008-04-12 17:00 | 嘯天豬

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @嘯天豬
            "左值未必都是可修改的,例如數(shù)組名就是不可修改的左值":數(shù)組名不是左值。注意我說(shuō)的話:*返回*可修改對(duì)象……數(shù)組名是一個(gè)* const,不是左值。簡(jiǎn)言之:int a[10];可以有int * p = a; a[10] = x;但不能有a = p;
            “但是對(duì)于user defined type 的右值,在某些情況下是允許被修改;例如對(duì)于函數(shù)返回的臨時(shí)對(duì)象,調(diào)用non-const member function是合法的”:臨時(shí)對(duì)象不一定是右值。*返回*不可修改對(duì)象……
            討論就是討論,沒(méi)有罵人的,看來(lái)大家都是好人。哈哈,這里不錯(cuò)。
            2008-04-17 13:07 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            sorry,上面有個(gè)錯(cuò)誤:a[10] = x; 改為 a[0] = x;
            2008-04-17 13:08 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @cuigang
            請(qǐng)注意我的用詞(有咬文嚼字之嫌,見諒):返回、對(duì)象、表達(dá)式。對(duì)象包括很多:指針、字面常量、臨時(shí)對(duì)象……我認(rèn)為我們之間的分歧在于你把我說(shuō)的對(duì)象細(xì)分了。

            “但 & 操作符的確只能應(yīng)用于有左值的表達(dá)式”——你是對(duì)的,我的錯(cuò)誤。

            “至于你鏈接的文章,請(qǐng)恕我未能洞悉,不知里面哪里提到 解引用操作符可以用于右值,或者隱含此意味。”——實(shí)際我想說(shuō)明的就是“但是間接尋址(indirection)反而說(shuō)明了你的觀點(diǎn),它是將指針變量的右值作為地址來(lái)訪問(wèn)指向物,類似的有‘.’,‘->’運(yùn)算符。”,因?yàn)槲野阎羔槷?dāng)作對(duì)象的一種。

            “我說(shuō)指向數(shù)組的指針費(fèi)解,不是說(shuō)我不理解,只是說(shuō)大多數(shù)人實(shí)際中難以見到,不好理解,如果你可以理解,你可以說(shuō)說(shuō)它和多維數(shù)組 arr[][] 的 指針 arr[2] 有什么區(qū)別。”我相信你理解了,否則也不會(huì)寫出這么有深度的文章。T arr[]中arr的類型是T[],&arr的類型就是T(*)[];但是,T arr[][]中arr的類型是T * arr[],&arr的類型是T**——最后這點(diǎn)是因?yàn)镃中二位數(shù)組是線性存儲(chǔ)的,不是我們所理解的二維矩陣。

            ——向你的認(rèn)真致敬!呵呵
            2008-04-17 13:42 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @raof01

            跟你先前的評(píng)論比較,想必你最近也深入研究了這個(gè)問(wèn)題,雖然言語(yǔ)之中仍然為自己辯護(hù),不過(guò)大家觀點(diǎn)畢竟更加接近了,其實(shí)我們對(duì)于這個(gè)問(wèn)題的理解可能都有少許偏差,但討論之后一定更加接近正確了。

            謝謝你捧場(chǎng)。
            2008-04-17 13:54 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @cuigang
            你舉的例子x=x+1;其中x無(wú)論是在左邊還是右邊都是左值,表達(dá)式"x+1"才是右值。
            2008-04-17 14:17 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @raof01

            你要說(shuō) x + 1 中的 x 是左值, 我真的很無(wú)奈。
            2008-04-17 23:18 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @cuigang
            你別無(wú)奈啊,給個(gè)理由先。
            我的依據(jù)是:左/右值指的是表達(dá)式。單純就x這個(gè)表達(dá)式來(lái)說(shuō),它是個(gè)左值,無(wú)論在=左邊還是右邊。
            2008-04-18 10:05 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @cuigang
            我始終不同意這句話:“表達(dá)式的左值是它的地址,右值是該地址所存儲(chǔ)的內(nèi)容。”因?yàn)闊o(wú)論地址還是內(nèi)容,都是對(duì)象。而且按照你這句話,x = x + 1;第一個(gè)x是個(gè)地址,第二個(gè)x是其內(nèi)容,假設(shè)x是T類型,那么上述表達(dá)式就應(yīng)該理解為=左邊是個(gè)地址,也就是T*,對(duì)吧?矛盾就來(lái)了,你把T類型的值賦給了T*。
            “雖然言語(yǔ)之中仍然為自己辯護(hù),不過(guò)大家觀點(diǎn)畢竟更加接近了”——?jiǎng)偛庞肿屑?xì)看了一遍你的文章,我堅(jiān)持我第一個(gè)評(píng)論里的觀點(diǎn),除了“&操作符能作用于左值和右值”這個(gè)錯(cuò)誤。
            我認(rèn)為:因?yàn)槟愕牡谝粋€(gè)觀點(diǎn)是全文的核心,所以我們之間還存在巨大的分歧。
            2008-04-18 10:19 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @raof01

            本來(lái)我以為我們的觀點(diǎn)接近了,但是看到你說(shuō) x + 1 的 x 是左值, 我就知道我們根本沒(méi)有持相同觀點(diǎn).

            現(xiàn)在,我解釋一下為什么 x + 1 中的 x 是右值, 首先要明確對(duì)于一個(gè)表達(dá)式,究竟是左值還是右值, 取決于它在表達(dá)式中的位置, 它并不是一定為左值或者右值,這一點(diǎn)你可以去看c++標(biāo)準(zhǔn),如果你對(duì)這點(diǎn)都不認(rèn)同,我們其實(shí)已經(jīng)無(wú)法再繼續(xù)討論了。

            其次,對(duì)于一個(gè)表達(dá)式,它都會(huì)有一個(gè)對(duì)象和它對(duì)應(yīng),無(wú)論它是一個(gè)變量,還是能產(chǎn)生一個(gè)臨時(shí)對(duì)象,或者是一個(gè)字面常量(自演算表達(dá)式). 這一點(diǎn)你應(yīng)該是同意的. 那么一個(gè)對(duì)象, 其實(shí)是一個(gè)映射關(guān)系, 它實(shí)際存在在內(nèi)存中(或者寄存器中), 它一定有位置信息和值信息(當(dāng)然得到值還需要類型信息), 符號(hào)表是在編譯時(shí)轉(zhuǎn)換用的,運(yùn)行時(shí)雖然沒(méi)有這個(gè)表存在,但這個(gè)映射關(guān)系是存在的. 變量就表示了這層關(guān)系.

            表達(dá)式 x 的運(yùn)算結(jié)果就是 x , 但是這個(gè)運(yùn)算結(jié)果是 x 本身嗎? 答案是否定的, 眾所周知, 內(nèi)存單元是無(wú)法做算術(shù)運(yùn)算的, x 的值 需要被取到 寄存器中, 然后才能加 1 . 如果你看匯編, 你會(huì)看到 一個(gè) 類似 lea 的指令, 所以 x 代表了它的值(先不管是左值還是右值).

            對(duì)于一個(gè)非引用類型的a, a=b , 是會(huì)讓 a 和 b 變成同一個(gè)對(duì)象嗎? 不是, 只是讓 a 和 b 的值相等.

            象basic那樣,給賦值加上一個(gè)let, let a = b, 這個(gè)a 是符號(hào)表中的那個(gè)a嗎? 一定. b是符號(hào)表中那個(gè)b嗎? 不必. 其實(shí)編譯器也是這么認(rèn)為的, 如果 b 的值 已經(jīng)被取到寄存器,它不會(huì)再取一次. 就象讀起來(lái)那樣, 讓a等于b, 只要跟b相等就好, b的位置在哪里無(wú)所謂, 但a在哪里就很重要了,否則就會(huì)給錯(cuò)人.

            說(shuō)的很亂,可能看不懂,其實(shí)回到本來(lái)的字面,左值就是放到等號(hào)左邊的值,右值就是放到右邊的值. 從 a = b 可以看出, 左值表示位置, 右值表示內(nèi)容(也就是值).

            再回到 x + 1, x + 1 會(huì)改變 x 嗎? 不會(huì), 那么不一定需要x ,更不需要 x 的位置, 一個(gè)和 x 相等的對(duì)象也行, 所以, 這里的x 是右值.

            對(duì)于非命令式語(yǔ)言, 就沒(méi)有左右值的煩惱, 命令式語(yǔ)言著實(shí)的麻煩. 怎么做的,解釋起來(lái)都費(fèi)勁.

            呵呵.

            2008-04-18 11:01 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @cuigang
            仔細(xì)查閱了一些資料,發(fā)現(xiàn)對(duì)于lvalue和rvlaue的說(shuō)明各有不同。找了兩個(gè)比較經(jīng)典的說(shuō)法,共同參考一下。下面是在comp.lang.c++.moderated上找到的(為避免斷章取義,貼全文):
            The simplest explanation I know is that an rvalue, in current C++, is an *expression* that produces a value, e.g. 42, and an lvalue is an *expression* that just refers to some existing object or function[1]. Hence the acronym "locator value"[2], which however is still misleading because an lvalue is simply not a value. Better would be *rexpression* versus *lexpression*, and even better, just value versus reference (unfortunately the term "reference" is already hijacked).

            "object" versus "value": in C++ the basic definition of "object" is a region of storage, i.e. anything that actually occupies storage, while a pure value such as 42 doesn't necessarily occupy any storage. A value (an rvalue) can be an object, though. If it is, then it's a temporary object.

            C++ allows you to call member functions on a class type rvalue, i.e. on a temporary class type object.

            The ability to call member functions on (class type) rvalues, together with C++'s treatment of assignment operator as a member function (automatically generated if needed and none defined), means that you can assign to class type rvalues. However, C++ does not regard that rvalue to be *modifiable*: to be
            well-defined, the assignment must do something else than modifiying the object assigned to (and typically we indicate that by declaring the assignment operator const). §3.10/14 "A program that attempts to modify an object through a nonmodifyable lvalue or rvalue expression is ill-formed".

            Fine point: §3.10/14 means that rvalue-ness transfers to parts of an rvalue, which are thereby also considered rvalues. However, at least the two compilers I use don't seem to know that rule. Comeau Online does.

            I'm not sure if the explanation above holds up with respect to C++0x rvalue references. rvalue versus lvalue got a lot more complicated in C++ than in original C. Perhaps it's even more complicated in C++0x, I don't know. :-)

            Cheers, & hth.,
            - Alf

            Notes:
            [1] Amazingly that's also the general definition the standard starts out with, before going into details: §3.10/2 "An lvalue refers to an object or function", however, it would have helped much if the word "expression" was explicitly included there, not just by being mentioned in the preceding paragraph.
            [2] Unfortunately the C++ standard doesn't use or even mention the acronym "locator value". This acronym comes from the current C standard. And ironically the C++ standard mentions, by contextual placement, the original old C acronym of "left hand value", in §3.10/4: "built-in assignment operators all expect their left hand operands to be lvalues".

            Programming Cpp的解釋:
            http://etutorials.org/Programming/Programming+Cpp/Chapter+3.+Expressions/3.1+Lvalues+and+Rvalues/

            你的解釋更接近真相,呵呵,不過(guò)我還是不同意地址一說(shuō),用引用會(huì)比較好一些。要不你整理一下,就lvalue和rvalue專門寫一篇?

            看來(lái)俺還得多看看標(biāo)準(zhǔn)啊。
            我的C++標(biāo)準(zhǔn)丟了,給發(fā)一個(gè)?raof01@gmail.com。
            2008-04-18 14:13 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @raof01

            C++03 標(biāo)準(zhǔn)
            http://www.newsmth.net/bbsanc.php?p=335-15-1-4-2

            我覺(jué)得有必要再羅嗦幾句

            關(guān)于數(shù)組名是不是左值,C++標(biāo)準(zhǔn)中我沒(méi)找到具體條目,不過(guò)在C中,《Expert C Programming》4.3.1 確實(shí)提到”Hence,arrayname is a lvalue but not modifiable lvalue“

            我把左值理解為”object with a name“,數(shù)組名在此范圍之內(nèi)



            右值這個(gè)概念,本質(zhì)上是與可修改沒(méi)有關(guān)聯(lián)的

            關(guān)于rvalue,常見的誤解是”不可修改“。并不是這樣的,右值并不是根據(jù)“不可修改”這個(gè)性質(zhì)來(lái)定義的

            首先,函數(shù)的返回值一定是右值,除非返回的是引用

            C++03 3.10.5
            “The result of calling a function that does not return a reference is an rvalue.”

            其次,右值是否能修改要看其是否是const-qualified

            C++03 3.10.9
            “Class rvalues can have cv-qualified types; non-class rvalues always have cv-unqualified types.”

            也就是說(shuō),對(duì)于UDT,右值是否可修改要看這個(gè)右值是否被限定為const

            舉個(gè)例子

            class A
            {
            public:
            void foo() {}
            void fooc() const {}
            };

            A func() { return A();}
            const A func2() {return A();}

            func().foo(); //Ok
            func().fooc(); //Ok
            func2().foo(); //Error,對(duì)const rvalue調(diào)用non-const member function
            func2().fooc(); //OK

            func和func2的區(qū)別在于返回值(rvalue)是否限定為const──對(duì)于UDT,有沒(méi)有這個(gè)const限定的結(jié)果顯然不同

            至于“臨時(shí)對(duì)象不一定是右值”,我想不出什么情況下臨時(shí)對(duì)象不是右值
            2008-04-19 06:23 | 嘯天豬

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @嘯天豬
            數(shù)組名是lvalue。但lvalue不是object with name,而是內(nèi)存區(qū)域的引用。這個(gè)問(wèn)題我更傾向于cuigang的說(shuō)法,雖然他用的是地址。
            臨時(shí)對(duì)象是右值,呵呵。
            我對(duì)于lvalue和rvalue的理解基本上是錯(cuò)誤的,呵呵,多謝cuigang和豬了。
            2008-04-19 12:35 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            @raof01

            善哉善哉
            2008-04-19 21:26 | cuigang

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            如果:
            “* 操作符應(yīng)用與左值表達(dá)式,以表達(dá)式左值為地址,取出表達(dá)式類型的值,作為右值返回。”

            那么:
            int foo(int *p)
            {
            return (*p)++; // Or *p += 1;
            }
            如何解釋?
            2008-07-28 14:46 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換[未登錄](méi)  回復(fù)  更多評(píng)論   

            表達(dá)式的lvalue是不可修改的,可修改的只有其rvalue。因?yàn)楫?dāng)一個(gè)表達(dá)式具有l(wèi)value時(shí),它在內(nèi)存中的位置是固定的,也就是lvalue是固定的。所謂修改表達(dá)式的值只是通過(guò)其lvalue來(lái)修改其rvalue。
            比如
            int i = 10;
            假定i的地址為0x1000,那么i的lvalue是0x1000,rvalue是10,
            i = 100;
            則表示0x1000存放的內(nèi)容也就是rvalue被修改成100,而不是i的lvalue——0x1000被修改成別的值,其內(nèi)容為100。
            2008-07-28 15:21 | raof01

            # re: 數(shù)組類型、函數(shù)類型到左值和右值的轉(zhuǎn)換  回復(fù)  更多評(píng)論   

            @raof01

            這句話說(shuō)得確實(shí)有問(wèn)題,應(yīng)該是把表達(dá)式的值(右值)作為地址(但不是表達(dá)式的左值),取出內(nèi)容。

            謝謝指正。
            2008-08-03 13:45 | cuigang
            久久精品国产亚洲7777| 国产精品久久久久久一区二区三区| 久久综合久久鬼色| 青春久久| 日韩AV无码久久一区二区| 成人久久久观看免费毛片| 国产亚州精品女人久久久久久| A级毛片无码久久精品免费| 国产亚洲精品美女久久久| 99久久精品国产一区二区三区| 97精品依人久久久大香线蕉97| 国产成人无码精品久久久久免费| 亚洲∧v久久久无码精品| 人人狠狠综合久久亚洲婷婷| 久久亚洲AV无码西西人体| 无码人妻久久一区二区三区免费 | 人妻系列无码专区久久五月天| 麻豆成人久久精品二区三区免费| 久久久国产精品| 久久婷婷国产麻豆91天堂| 久久中文字幕视频、最近更新| 国产99久久九九精品无码| 久久免费看黄a级毛片| 久久精品国产72国产精福利| 欧美精品一本久久男人的天堂| 久久精品九九亚洲精品| 国产毛片久久久久久国产毛片 | 精品国产91久久久久久久| 久久久久亚洲AV片无码下载蜜桃| 久久精品国产99久久香蕉| 性高湖久久久久久久久| 日韩人妻无码精品久久久不卡 | 久久se精品一区二区影院 | 久久久久一本毛久久久| 日产精品久久久久久久| 色狠狠久久综合网| 国产69精品久久久久9999APGF| 久久天天躁夜夜躁狠狠躁2022| 久久精品国产欧美日韩99热| 精品久久久久中文字| 狠狠色丁香婷婷久久综合不卡|