簡體   English   中英

在C ++中,所有的臨時都是rvalues嗎?

[英]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解釋了為什么這個問題沒有意義。 歸結為:

  • rvalue-ness是表達式的(boolean)屬性 - 每個表達式都是左值或右值
  • 臨時的不是表達

出於這個原因,這個問題沒有意義。

一個很好的例子是以下代碼:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM