[英]Are all temporaries rvalues in C++?
過去幾年我一直用C ++編寫代碼。 但有一個問題我無法弄清楚。 我想問一下,C ++,rvalues都是臨時工嗎?
如果不是,任何人都可以提供一個例子,其中代碼中的臨時生成是左值 ?
沒有。
C ++語言規范永遠不會像你要問的那樣直截了當地斷言。 它並沒有在語言標准中的任何地方說“所有臨時對象都是右值”。 此外,問題本身有點用詞不當,因為在C ++語言中作為rvalue的屬性不是對象的屬性,而是表達式的屬性(即其結果的屬性)。 這實際上就是它在語言規范中的定義:對於不同類型的表達式,當結果是左值時,它表示為右值。 除此之外,這實際上意味着臨時對象可以作為右值和左值訪問,具體取決於用於執行訪問的特定表達形式。
例如,文字2 + 3
表達式的結果顯然是rvalue,類型為int
的臨時值。 我們不能一元申請&
於它,因為一元&
需要一個左值作為其操作數
&(2 + 3); // ERROR, lvalue required
但是,眾所周知,常量引用可以附加到臨時對象,如
const int &ri = 2 + 3;
在這種情況下,引用附加到臨時,延長后者的生命周期。 顯然,一旦完成,我們有權訪問非常相同的臨時當作左值ri
,因為引用總是左值。 例如,我們可以輕松合法地將一元&
應用於引用並獲取指向臨時的指針
const int *pi = &ri;
只要臨時持續存在,指針仍保持完全有效。
左值訪問臨時對象的另一個明顯例子是當我們通過this
指針訪問類類型的臨時對象時。 *this
的結果是一個左值(總是將一元*
的結果應用於數據指針的情況),但它並沒有改變實際對象可能很容易成為臨時對象的事實。 對於給定的類類型T
,表達式T()
是一個rvalue,如語言標准中明確規定的那樣,但臨時對象通過*T().get_this()
表達式訪問(帶有明顯的T::get_this()
)是一個左值。 與前面的示例不同,此方法允許您立即獲取非const限定的左值,該值引用臨時對象。
因此,同樣的臨時對象可能很容易被“看作”為右值或左值,具體取決於您用來“查看”該對象的表達式( 訪問路徑類型 )。
Prasoon Saurav已經鏈接了一個非常好的clc ++線程。 在那里,James Kanze解釋了為什么這個問題沒有意義。 歸結為:
出於這個原因,這個問題沒有意義。
一個很好的例子是以下代碼:
int main() {
const int& ri = 4;
std::cout << ri << std::endl;
}
值為4
的臨時int不是表達式。 打印的表達式ri
不是暫時的。 這是一個左值,指的是臨時的。
好吧,那個數組運算符返回一個引用,任何返回引用的函數都可以被認為是做同樣的事情? 所有引用都是const,雖然它們可以是左值,但它們會修改它們引用的內容,而不是引用本身。 *
運算符也是如此,
*(a temp pointer) = val;
我發誓我以前使用一些編譯器將臨時值傳遞給任何帶參考的函數,
所以你可以去:
int Afunc()
{
return 5;
}
int anotherFunc(int & b)
{
b = 34;
}
anotherFunc(Afunc());
現在找不到一個允許你這樣做的,引用必須是const才能允許傳遞臨時值。
int anotherFunc(const int & b);
無論如何,引用可以是左值和臨時,訣竅是引用它的自我不被修改,只有它引用的內容。
如果將->
運算符計為運算符,則臨時指針可以是左值,但是同樣的條件適用,它不是將要更改的臨時指針,而是它所指向的東西。
數組索引操作既是臨時值也是左值,類似[10] = 1就是你要找的東西的一個例子; 左值是一個臨時的計算指針。
這取決於你認為臨時變量是什么。 你可以寫類似的東西
#include <stdio.h>
int main()
{
char carray[10];
char *c=carray+1;
*(c+2+4) = 9;
printf("%d\n",carray[7]);
return 0;
}
這在VisualStudios和GCC中運行。 您可以在鍵盤中運行代碼
我認為(c + 2 + 4)是一個右值,雖然我想分配給它。 當我取消引用它時,它將成為左值。 所以,所有的臨時都是rvalues。 但是你可以通過解除引用來使rvalues(因此是臨時的)成為左值
簡短的回答:是的,但我不會引用標准,因為證明這一點需要解決各種臨時問題。 根據定義,臨時具有一個語句的生命周期,因此將事物分配給一個語句最好是不好的風格。
有趣的答案:復制省略可以使(通常是)一個與左值對象相同的臨時對象。 例如,
MyClass blah = MyClass( 3 ); // temporary likely to be optimized out
要么
return MyClass( 3 ); // likely to directly initialize object in caller's frame
編輯:關於在這些情況下是否有任何臨時對象的問題,§12.8/ 15提到
通過將臨時對象直接構造到省略副本的目標中,可以省略復制操作
這表明有一個臨時對象可能與左值相同。
如果不是,任何人都可以提供一個例子,其中代碼中的臨時生成是左值?
以下代碼綁定對編譯器創建的const float
類型的臨時對象的常量引用:
int i;
const float &cfr = i;
行為是“ 好像 ”:
int i;
const float __tmp_cfr = i; // introduced by the compiler
const float &cfr = __tmp_cfr;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.