說對象是那麼「this」的類型是什麼?爲什麼「這個」不是左翼?
class A {
public : void Silly(){
this = 0x12341234;
}
我知道我會得到編譯器錯誤「‘這’不是一個左值」。但那也不是暫時的。那麼「這個」的假設聲明是什麼?
編譯器:Mac上的GCC 4.2編譯器。
說對象是那麼「this」的類型是什麼?爲什麼「這個」不是左翼?
class A {
public : void Silly(){
this = 0x12341234;
}
我知道我會得到編譯器錯誤「‘這’不是一個左值」。但那也不是暫時的。那麼「這個」的假設聲明是什麼?
編譯器:Mac上的GCC 4.2編譯器。
對於某些X類,this
的類型爲X* this;
,但不允許分配給它,因此即使它實際上沒有類型X *const this
,它的行爲幾乎與防止分配一樣去。正式的,這是一個prvalue
,與類似於整數文字的類似,所以試圖賦予它大致相當於試圖給'a'
或10
分配一個不同的值。
注意,在早期 C++,this
是一個左值 - 分配給this
被允許 - 你這樣做來處理對象的內存分配,依稀相似超載new
和delete
的類(WASN當時還沒有支持)。
好吧,明白了。我刪除了我不必要的評論。 – AnT
首先,this
不是一個變量 - 它是一個關鍵字。當用作右值時,其類型爲A *
或A const *
。在現代C++中,禁止分配到this
。你也不能拿到this
的地址。換句話說,它不是一個有效的左值。
「*當用作右值時,它的類型是'A *'或'A * const'。*」您的意思是'A *'或'一個const *'。 – ildjarn
對。該死的關於指針常量的混淆。 –
@Seva:有一個簡單的規則可以幫助保持清晰。如果你看看'T * p;'這樣的聲明,'T'是目標類型,'p'是指針本身的名稱,'*'是兩者之間的「牆」。如果將'const'(或'volatile')放在牆的指針一側,它會影響指針。如果將它放在牆的「類型」一側,它會影響指針指向的類型。 –
由於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; }
};
這是不可能的this
提供一個 「聲明」。沒有辦法在C++中「聲明」右值。如你所知,this
是一個右值。
左值和右值是產生這些值的表達式的屬性,而不是聲明或對象的屬性。在這方面,甚至可以爭辯說也不可能宣佈一個左值。你聲明一個對象。左值是將該對象的名稱用作表達式時產生的值。在這個意義上,「宣佈一個右值」和「宣佈一個左值」都是矛盾表達式。
你的問題似乎也表明,「作爲左值」和「作爲臨時」的屬性在某種程度上是互補的,即所有東西都被認爲是左值或臨時值。實際上,「臨時」的財產在這裏沒有任何生意。所有表達式都是左值或右值。而this
恰好是一個右值。
另一方面,臨時性可視爲右值或左值,具體取決於您如何訪問臨時值。
P.S.注意,BTW,在C++(而不是C)中,普通函數是左值。
好吧,來自C背景我傾向於看到右值的聲明爲「常量左值類型」 –
@Ajeet:這真的很奇怪。 C語言在這方面與C++沒有多大區別。在C語言中,'const int'聲明瞭**左值**,而不是右值。 – AnT
雖然你不能聲明右值,但你可以(例如)聲明/定義一個類型的左值,該值可以在沒有轉換的情況下分配給它。 –
要回答的第二部分,「爲什麼是this
不是左值」,我猜測,以該委員會的實際動機,但優勢包括:
this
沒有太大的邏輯意義,所以沒有特別需要它出現在作業的左側。讓它成爲一個右值強調,禁止它是沒有多大意義的,並且意味着標準不必定義如果你這樣做會發生什麼。register
修改後的自動變量。它可以例如在非靜態成員函數中使用寄存器來存儲this
。如果你使用const引用,那麼除非使用允許狡猾優化,否則它需要被複制到某個具有地址的地方,但是如果你連續兩次執行它,至少它不需要是相同的地址,因爲它需要如果this
是一個聲明的變量。要在布丁中看到證明,我正在玩這個:const int i = 10; *(int *)((void *)&i)= 20;這是有效的。但是我不能這樣做,因爲我不能申請'這個'。 –
是的,儘管IIRC標準實際上並沒有定義「有效程序」或「有效代碼」。你的代碼格式良好,但有未定義的行爲,有些人似乎稱之爲「無效」。但是,你的觀點是:你可以用常量左值做一個愚蠢的事情,但是用右值不能這麼容易。與'this'配合使用的類似技巧是'template
+1嗯,所以模板的東西還沒有做到萬無一失。 :) –
強制性'try {this = madness; } catch(...){this = sparta; }' – corsiKa
出於興趣,哪個編譯器給你這個消息? –
@Oli:如果代碼改爲'this =(A *)0x12341234;',VC++報告「*左操作數必須是l值*」 - 類似。 – ildjarn