2011-09-07 55 views
5

說對象是那麼「this」的類型是什麼?爲什麼「這個」不是左翼?

class A { 
public : void Silly(){ 
    this = 0x12341234; 
} 

我知道我會得到編譯器錯誤「‘這’不是一個左值」。但那也不是暫時的。那麼「這個」的假設聲明是什麼?

編譯器:Mac上的GCC 4.2編譯器。

+4

強制性'try {this = madness; } catch(...){this = sparta; }' – corsiKa

+0

出於興趣,哪個編譯器給你這個消息? –

+0

@Oli:如果代碼改爲'this =(A *)0x12341234;',VC++報告「*左操作數必須是l值*」 - 類似。 – ildjarn

回答

6

對於某些X類,this的類型爲X* this;,但不允許分配給它,因此即使它實際上沒有類型X *const this,它的行爲幾乎與防止分配一樣去。正式的,這是一個prvalue,與類似於整數文字的類似,所以試圖賦予它大致相當於試圖給'a'10分配一個不同的值。

注意,在早期 C++,this是一個左值 - 分配給this被允許 - 你這樣做來處理對象的內存分配,依稀相似超載newdelete的類(WASN當時還沒有支持)。

+0

好吧,明白了。我刪除了我不必要的評論。 – AnT

3

首先,this不是一個變量 - 它是一個關鍵字。當用作右值時,其類型爲A *A const *。在現代C++中,禁止分配到this。你也不能拿到this的地址。換句話說,它不是一個有效的左值。

+2

「*當用作右值時,它的類型是'A *'或'A * const'。*」您的意思是'A *'或'一個const *'。 – ildjarn

+0

對。該死的關於指針常量的混淆。 –

+2

@Seva:有一個簡單的規則可以幫助保持清晰。如果你看看'T * p;'這樣的聲明,'T'是目標類型,'p'是指針本身的名稱,'*'是兩者之間的「牆」。如果將'const'(或'volatile')放在牆的指針一側,它會影響指針。如果將它放在牆的「類型」一側,它會影響指針指向的類型。 –

1

由於this是一個指向與該類相同類型的類的實例的常量指針,因此會出現編譯器錯誤。儘管可以用它來改變非const限定方法,調用方法和操作符中的其他類成員,但不能指派給它。另請注意,因爲這是一個靜態方法沒有this指針的實例。

假設:

class Whatever 
{ 
    // your error because this is Whatever* const this; 
    void DoWhatever(const Whatever& obj) { this = &obj; } 

    // this is ok 
    void DoWhatever(const Whatever& obj) { *this = obj; } 

    // error because this is now: const Whatever* const this; 
    void DoWhatever(const Whatever& obj) const { *this = obj; } 

    // error because this doesn't exist in this scope 
    static void DoWhatever(const Whatever& obj) { *this = obj; } 
}; 
4

這是不可能的this提供一個 「聲明」。沒有辦法在C++中「聲明」右值。如你所知,this是一個右值。

左值和右值是產生這些值的表達式的屬性,而不是聲明或對象的屬性。在這方面,甚至可以爭辯說也不可能宣佈一個左值。你聲明一個對象。左值是將該對象的名稱用作表達式時產生的值。在這個意義上,「宣佈一個右值」和「宣佈一個左值」都是矛盾表達式。

你的問題似乎也表明,「作爲左值」和「作爲臨時」的屬性在某種程度上是互補的,即所有東西都被認爲是左值或臨時值。實際上,「臨時」的財產在這裏沒有任何生意。所有表達式都是左值或右值。而this恰好是一個右值。

另一方面,臨時性可視爲右值或左值,具體取決於您如何訪問臨時值。

P.S.注意,BTW,在C++(而不是C)中,普通函數是左值。

+0

好吧,來自C背景我傾向於看到右值的聲明爲「常量左值類型」 –

+0

@Ajeet:這真的很奇怪。 C語言在這方面與C++沒有多大區別。在C語言中,'const int'聲明瞭**左值**,而不是右值。 – AnT

+0

雖然你不能聲明右值,但你可以(例如)聲明/定義一個類型的左值,該值可以在沒有轉換的情況下分配給它。 –

2

要回答的第二部分,「爲什麼是this不是左值」,我猜測,以該委員會的實際動機,但優勢包括:

  1. 分配給this沒有太大的邏輯意義,所以沒有特別需要它出現在作業的左側。讓它成爲一個右值強調,禁止它是沒有多大意義的,並且意味着標準不必定義如果你這樣做會發生什麼。
  2. 使它成爲一個右值可以防止你獲取一個指針,從而減少任何需要提供地址的實現,就像register修改後的自動變量。它可以例如在非靜態成員函數中使用寄存器來存儲this。如果你使用const引用,那麼除非使用允許狡猾優化,否則它需要被複制到某個具有地址的地方,但是如果你連續兩次執行它,至少它不需要是相同的地址,因爲它需要如果this是一個聲明的變量。
+0

要在布丁中看到證明,我正在玩這個:const int i = 10; *(int *)((void *)&i)= 20;這是有效的。但是我不能這樣做,因爲我不能申請'這個'。 –

+1

是的,儘管IIRC標準實際上並沒有定義「有效程序」或「有效代碼」。你的代碼格式良好,但有未定義的行爲,有些人似乎稱之爲「無效」。但是,你的觀點是:你可以用常量左值做一個愚蠢的事情,但是用右值不能這麼容易。與'this'配合使用的類似技巧是'template T&stupid(const T&r){return const_cast (r);}'後面跟着'stupid(this)= 0;'。不建議。 –

+0

+1嗯,所以模板的東西還沒有做到萬無一失。 :) –