• <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, 評論 - 137, 引用 - 0
            數(shù)據(jù)加載中……

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

            1、左值和右值

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

            = x + 1;

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

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

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

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

            T* a; 

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

            T arr[100];

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

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

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

            特別要強(qiáng)調(diào)的是,arr 的類型和 f 的類型都不是指針。這兩個類型的表達(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)]有右值,所以特別這里要說明數(shù)組類型和函數(shù)類型到右值的轉(zhuǎn)換。比如上文所說 arr ,當(dāng)它作為賦值操作符的操作數(shù)時,它需要轉(zhuǎn)換為 T* 類型的指針(注意類型是指針!!),其值等于第一個元素的地址。而上文中所說的 f,當(dāng)它作為賦值操作符的操作數(shù)時,它需要轉(zhuǎn)換為 T(*)(void) 的指針(注意類型是指針!!),它指向f的地址。

            5、對數(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ù)組的指針(這個比較費(fèi)解)

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

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

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

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

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




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

            評論

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

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

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

            給樓上的糾兩個錯:

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

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

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

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

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

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

            @raof01

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

            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 這樣說:

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

            左值代表了一個可被程序?qū)ぶ返膶ο螅梢詮脑搶ο笞x取一個值,除非該對象被聲明為const,否則它的值也可以被修改。相對來說,右值只是一個表達(dá)式,它表示了一個值,或一個引用了臨時對象的表達(dá)式,用戶不能尋址該對象,也不能改變它的值。

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

            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.

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

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

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

            2008-04-08 21:44 | cuigang

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

            哪個是對的,不要誤解人
            2008-04-09 16:14 | 我愛你

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

            @cuigang
            想太多反而會把問題搞復(fù)雜。

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

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

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

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

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

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

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

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

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

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

            至于左值/右值的準(zhǔn)確含義,還是參考標(biāo)準(zhǔn)吧;書畢竟是面向大眾的,通常不會像標(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)換[未登錄]  回復(fù)  更多評論   

            @嘯天豬

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

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

            @ww

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

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

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

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

            @嘯天豬
            @cuigang

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

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

            在VC中編譯時對后兩行都會提示“++需要左值”。

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

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

            @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的地址對程序員無意義──它的地址對編譯器有用,對程序員是沒用的

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

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

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

            而標(biāo)準(zhǔn)規(guī)定,前綴/后綴增量的操作對象必須是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!“++出錯的原因在于這里發(fā)生了string literal 到 pointer的自動轉(zhuǎn)換,”hello wolrd“轉(zhuǎn)換為類型為char *的rvalue。對于一個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ù)  更多評論   

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

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

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

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

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

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

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

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

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

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

            @raof01

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

            謝謝你捧場。
            2008-04-17 13:54 | cuigang

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

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

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

            @raof01

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

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

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

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

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

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

            @raof01

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

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

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

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

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

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

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

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

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

            呵呵.

            2008-04-18 11:01 | cuigang

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

            @cuigang
            仔細(xì)查閱了一些資料,發(fā)現(xiàn)對于lvalue和rvlaue的說明各有不同。找了兩個比較經(jīng)典的說法,共同參考一下。下面是在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/

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

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

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

            @raof01

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

            我覺得有必要再羅嗦幾句

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

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



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

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

            首先,函數(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.”

            也就是說,對于UDT,右值是否可修改要看這個右值是否被限定為const

            舉個例子

            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,對const rvalue調(diào)用non-const member function
            func2().fooc(); //OK

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

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

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

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

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

            @raof01

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

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

            如果:
            “* 操作符應(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)換[未登錄]  回復(fù)  更多評論   

            表達(dá)式的lvalue是不可修改的,可修改的只有其rvalue。因?yàn)楫?dāng)一個表達(dá)式具有l(wèi)value時,它在內(nèi)存中的位置是固定的,也就是lvalue是固定的。所謂修改表達(dá)式的值只是通過其lvalue來修改其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ù)  更多評論   

            @raof01

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

            謝謝指正。
            2008-08-03 13:45 | cuigang
            国内精品久久久久久久亚洲| 国产精品内射久久久久欢欢| 香蕉99久久国产综合精品宅男自| 久久国产精品无码网站| 亚洲精品99久久久久中文字幕| 人妻无码αv中文字幕久久琪琪布| 狠狠色婷婷久久综合频道日韩 | 国产精品18久久久久久vr | 久久精品国产99国产精品亚洲| 亚洲国产精品高清久久久| 99久久国产综合精品五月天喷水 | 91精品国产91久久| 久久亚洲国产精品成人AV秋霞| 好属妞这里只有精品久久| 欧美日韩精品久久久久| 国产 亚洲 欧美 另类 久久| 亚洲av日韩精品久久久久久a| 一本一道久久精品综合| 欧洲人妻丰满av无码久久不卡| 91精品国产91久久久久久蜜臀| 色欲久久久天天天综合网 | 一本久久a久久精品综合夜夜| 国产成人久久精品一区二区三区 | 久久久久久精品无码人妻| 亚洲国产精品久久久久婷婷软件| 免费无码国产欧美久久18| 激情五月综合综合久久69| 精品国产91久久久久久久| 亚洲精品乱码久久久久久自慰| 蜜桃麻豆www久久国产精品| 亚洲午夜久久影院| 免费观看久久精彩视频| WWW婷婷AV久久久影片| 久久久久亚洲AV成人片| 久久婷婷五月综合国产尤物app| 国产香蕉久久精品综合网| 久久久久久噜噜精品免费直播| 国产精品免费久久久久电影网| 狠狠色噜噜狠狠狠狠狠色综合久久| 久久超乳爆乳中文字幕| 69久久夜色精品国产69|